pubnub get history from multiple channels - react-native

I am using pubnub for chat , and using userid as channel to send messages , however when i want to retrieve conversation between two users , i need to get data from both channels, how can i do that?
I have data on both channels e.g. "userAid" and "userBid" but if i query
this.pubnub.history(
{ channel: ['userAid,'userBid'], reverse: true, count: 15 },
(status, res) => {
});```
it does not return any result , if i query with only one channel it works

The History SDK call is generally meant to fetch history from a single channel. If you need to fetch history from multiple channels, you need to use Batch History methods.
Refer to https://www.pubnub.com/docs/react-native-javascript/api-reference-storage-and-playback#batch-history for more details.
An example call might be as follows, but the link above provides a list of all the parameters that can be set. Please note that the fetchMessages method can be used to fetch history from a single channel as well.
pubnub.fetchMessages(
{
channels: ['ch1', 'ch2', 'ch3'],
start: "15343325214676133",
end: "15343325004275466",
count: 25
},
(status, response) => {
// handle response
}
);

It seems history can only get messages from one channel.
Try this:
pubnub.fetchMessages({
channels: ['ch1', 'ch2', 'ch3'],
start: '15343325214676133',
end: '15343325004275466',
count: 15,
}, (status, response) => {
// handle status, response
});
Pubnub docs on getting the history:
https://www.pubnub.com/developers/chat-resource-center/docs/reference/message-history

Related

database writes need to be verified in an integration test?

I basically have an api that writes to 2 different tables, and am using supertest to make api calls to write a certain data to the database e.g. POST /userCertificates writes his address in the address table, education in status table like so:
I basically do this as one of the integration tests:
payload = {user_id: 1, name: abc, address: {a: x, b: y}, education: {a: x, b: y} ...}
it('Post to the database'), ()=>{
request.post(/userCertificate).send(payload).expect(200)
.then(res =>
expect(payload.userAddress).toEqual(res.body.userAddress)
// more expects to verify the response received)
}
The /userCertificates api basically does this:
creates a new user with name and user_id
saves data of address to the address table and establishes FK relation.
saves data of education to the education table and establishes FK
relation.
But, the real confusion is, do I also need to use a dao layer that directly talks with the database to absolutely verify that the data has been written to the 2 tables? E.g.
for my case above(in the same describe block):
NOTE: user_id is a foreign key in the address and education table
it('Verify data written to the address table', ()=> {
const data = AddressDao.find({user_id: 1})
if(data.length <= 0) {
throw 'Data not written to the database
}
}
it('Verify data written to the education table', ()=> {
const data = EducationDao.find({user_id: 1})
if(data.length <= 0) {
throw 'Data not written to the database
}
}
But, not just in the case of writing to multiple tables, is such verification of data
written to the database required?

FaunaDB: how to fetch a custom column

I'm just learning FaunaDB and FQL and having some trouble (mainly because I come from MySQL). I can successfully query a table (eg: users) and fetch a specific user. This user has a property users.expiry_date which is a faunadb Time() type.
What I would like to do is know if this date has expired by using the function LT(Now(), users.expiry_date), but I don't know how to create this query. Do I have to create an Index first?
So in short, just fetching one of the users documents gets me this:
{
id: 1,
username: 'test',
expiry_date: Time("2022-01-10T16:01:47.394Z")
}
But I would like to get this:
{
id: 1,
username: 'test',
expiry_date: Time("2022-01-10T16:01:47.394Z"),
has_expired: true,
}
I have this FQL query now (ignore oauthInfo):
Query(
Let(
{
oauthInfo: Select(['data'], Get(Ref(Collection('user_oauth_info'), refId))),
user: Select(['data'], Get(Select(['user_id'], Var('oauthInfo'))))
},
Merge({ oauthInfo: Var('oauthInfo') }, { user: Var('user') })
)
)
How would I do the equivalent of the mySQL query SELECT users.*, IF(users.expiry_date < NOW(), 1, 0) as is_expired FROM users in FQL?
Your use of Let and Merge show that you are thinking about FQL in a good way. These are functions that can go a long way to making your queries more organized and readable!
I will start with some notes, but they will be relevant to the final answer, so please stick with me.
The Query function
https://docs.fauna.com/fauna/current/api/fql/functions/query
First, you should not need to wrap anything in the Query function, here. Query is necessary for defining functions in FQL that will be run later, for example, in the User-Defined Function body. You will always see it as Query(Lambda(...)).
Fauna IDs
https://docs.fauna.com/fauna/current/learn/understanding/documents
Remember that Fauna assigns unique IDs for every Document for you. When I see fields named id, that is a bit of a red flag, so I want to highlight that. There are plenty of reasons that you might store some business-ID in a Document, but be sure that you need it.
Getting an ID
A Document in Fauna is shaped like:
{
ref: Ref(Collection("users"), "101"), // <-- "id" is 101
ts: 1641508095450000,
data: { /* ... */ }
}
In the JS driver you can use this id by using documentResult.ref.id (other drivers can do this in similar ways)
You can access the ID directly in FQL as well. You use the Select function.
Let(
{
user: Get(Select(['user_id'], Var('oauthInfo')))
id: Select(["ref", "id"], Var("user"))
},
Var("id")
)
More about the Select function.
https://docs.fauna.com/fauna/current/api/fql/functions/select
You are already using Select and that's the function you are looking for. It's what you use to grab any piece of an object or array.
Here's a contrived example that gets the zip code for the 3rd user in the Collection:
Let(
{
page: Paginate(Documents(Collection("user")),
},
Select(["data", 2, "data", "address", "zip"], Var("user"))
)
Bring it together
That said, your Let function is a great start. Let's break things down into smaller steps.
Let(
{
oauthInfo_ref: Ref(Collection('user_oauth_info'), refId)
oauthInfo_doc: Get(Var("oathInfoRef")),
// make sure that user_oath_info.user_id is a full Ref, not just a number
user_ref: Select(["data", "user_id"], Var("oauthInfo_doc"))
user_doc: Get(Var("user_ref")),
user_id: Select("id", Var("user_ref")),
// calculate expired
expiry_date: Select(["data", "expiry_date"], Var("user_doc")),
has_expired: LT(Now(), Var("expiry_date"))
},
// if the data does not overlap, Merge is not required.
// you can build plain objects in FQL
{
oauthInfo: Var("oauthInfo_doc"), // entire Document
user: Var("user_doc"), // entire Document
has_expired: Var("has_expired") // an extra field
}
)
Instead of returning the auth info and user as separate points if you do want to Merge them and/or add additional fields, then feel free to do that
// ...
Merge(
Select("data", Var("user_doc")), // just the data
{
user_id: Var("user_id"), // added field
has_expired: Var("has_expired") // added field
}
)
)

Find entity with most relations filtered by criteria

model Player {
id String #id
name String #unique
game Game[]
}
model Game {
id String #id
isWin Boolean
playerId String
player Player #relation(fields: [playerId], references: [id])
}
I would like to find a player with most wins. How would I do that with prisma? If there is no prisma "native" way to do it, what is the most efficient way to do this with raw SQL?
The best I could think of is:
prisma.player.findMany({
include: {
game: {
where: {
isWin: true,
},
},
},
})
But it has huge downside that you need to filter and order results in Node manually, and also store all results in memory while doing so.
Using the groupBy API you can find the player with the most wins using two queries.
1. Activate orderByAggregateGroup
You'l need to use the orderByAggregateGroup preview feature and use Prisma version 2.21.0 or later.
Update your Prisma Schema as follows
generator client {
provider = "prisma-client-js"
previewFeatures = ["orderByAggregateGroup"]
}
// ... rest of schema
2. Find playerId of most winning player
Use a groupBy query to do the following:
Group games by the playerId field.
Find the count of game records where isWin is true.
Order them in descending order by the count mentioned in 2.
Take only 1 result (since we want the player with the most wins. You can change this to get the first-n players as well).
The combined query looks like this:
const groupByResult = await prisma.game.groupBy({
by: ["playerId"],
where: {
isWin: true,
},
_count: {
isWin: true,
},
orderBy: {
_count: {
isWin: "desc",
},
},
take: 1, // change to "n" you want to find the first-n most winning players.
});
const mostWinningPlayerId = groupByResult[0].playerId;
I would suggest checking out the Group By section of the Aggregation, grouping, and summarizing article in the prisma docs, which explains how group by works and how to use it with filtering and ordering.
3. Query player data with findUnique
You can trivially find the player using a findUnique query as you have the id.
const mostWinningPlayer = await prisma.player.findUnique({
where: {
id: mostWinningPlayerId,
},
});
Optionally, if you want the first "n" most winning players, just put the appropriate number in the take condition of the first groupBy query. Then you can do a findMany with the in operator to get all the player records. If you're not sure how to do this, feel free to ask and I'll clarify with sample code.

Razorpay response not sending Razorpay order_id

I am working on React Native Razorpay payment gateway integration.
I am using react-native-razorpay.
Code is below:-
Send Params are:-
var options = {
description: "Credits towards consultation",
image: "https://i.imgur.com/3g7nmJC.png",
currency: "INR",
key: "a-----b----ccc-dd",
amount: Math.round(Number(order_total).toFixed(2) * 100),
name: "Product",
prefill: {
email: email ? email : "v#razorpay.com",
contact: mobile ? mobile : "1111111111",
name:
firstname && lastname
? `${firstname} ${lastname}`
: "Razorpay Software"
},
theme: { color: theme.colors.primaryColor },
payment_capture: 1
};
Checkout Method:-
RazorpayCheckout.open(options)
.then(data => {
// handle success
console.log("payment success", data);
if (data && data.razorpay_payment_id) {
orderData.payment = data.razorpay_payment_id;
this.props.payMyOrder(orderData);
}
})
.catch(error => {
// handle failure
this.toast.show(error.description);
});
I am getting only razorpay_payment_id in response but, razorpay_payment_id and razorpay_signature are missing. Also, in Razorpay backend Razorpay Order Id and Order Id are missing.
hey as we can see in the above code options object that you are passing to the checkout you are not passing the order_id, you should pass the order_id as well. Since you are not passing the order_id the same is not getting returned to you after the payment is done. refer to the below link on how to create an order at your server-side.
https://razorpay.com/docs/api/orders/
if you pass the order_id in the request param to the checkout you'll get the order_id and signature as well in the payment response.
Please check the documentation we need to pass the order_id, here.
As per the documentation, once you pass the order_id, then only after payment successful razorpay returns the
razorpay_order_id,razorpay_payment_id and razorpay_signature.
After that you can compare the signature to get acknowledgement of payment success.
Just a note if your id is wrong your razorpaySignature too will not appear
Issue mostly will be because of invalid order Id, the order id received from Backend should be the one backend got from Razorpay.
Something like below should be used at your backend to generate order id (format of order id will be order_<some id>). You can get language based backend implementation at this link
var instance = new Razorpay({ key_id: 'YOUR_KEY_ID', key_secret: 'YOUR_SECRET' })
instance.orders.create({
amount: 50000,
currency: "INR",
receipt: "receipt#1",
notes: {
key1: "value3",
key2: "value2"
}
})

Duplicate console.log output of gun map when using gundb

Does this function duplicate results as a bug or am I causing this? The output always has 1 or more records duplicated. In this example, Bank of China is always listed twice in output.
gun.get('savings_accounts').map(function (name, ID) {
console.log( name.name, ID );
}, true)
My code:
localStorage.clear();
var gun = Gun();
////////////////////////////////////////////////////// create record
var acc1 = gun.put({
name: "Bank of America",
accType: "Savings",
last4: "4123",
favorite: true,
status: true,
created: "some date created"
});
var acc2 = gun.put({
name: "Bank of China",
accType: "Savings",
last4: "5123",
favorite: true,
status: true,
created: "some date created"
});
gun.get('savings_accounts').map(function (name, ID) {
console.log( name.name, ID );
}, true)
From the author of GunDB, Mark Nadal
1) gun.get('savings_accounts').map().val(cb) is what you want for normal / procedural / easy things.
HOWEVER...
2) gun is actually functional/reactive (FRP), or also known as streaming/event oriented. The data might/will get called multiple times (if you don't use .val) because A) in-memory replies, B) your browser's localStorage replies, C) the server will reply, D) server will relay to other browser peers which each might reply with data.
^ that is the "realtime" part of gun.
.val only fires once (well per item on the chain, so if you do map().val(cb) the val will get fired multiple times but only once from each item in the list).
use .val(cb) if you are doing procedural things.
Use .on(cb) (which is what .map(cb) uses internally. Most API methods internally use .on) if you want to subscribe to realtime updates of the data.
you'll slowly find that the realtime/FRP/event/streaming as being a much cleaner way to write your apps.