How to use more than one pubsub in javascript grapql? - javascript

I want to use Google PubSub and Redis PubSub provided by Google Cloud in Javascript GraphQL(apollo-server).
I tried to create 2 subscription fields, but I couldn't get the result I wanted.
this, it said that subscriptions do not provide more than two root fields.
How can I subscribe to 2 pubSub objects?
The code I used is like below.
Subscription: {
operation: {
subscribe: withFilter(
(_, { channelId }, { pubSub }) => pubSub.asyncIterator(getTopic(channelId)),
(payload, variables) => {
// Some Code...
}
),
},
},

Related

How to perform two firebase database operation on different nodes in single request/function?

I am a react-native developer and new to firebase. I am performing firebase realtime database operation, have a look at code below;
firebase.database().ref('events/wedding/items').push(object).then((data) => {
//success callback
dispatch(addPendingInvoice({ ...invoice, id: data.key }))
Alert.alert('Successfully added to Invoices', 'Please go to invoice section to clear first and continue.', [{ text: 'Ok' }])
}).catch((error) => {
//error callback
Alert.alert("Can't book package.", 'Please check your internet connection!', [{ text: 'OK', style: 'destructive' }])
})
Now, I wish to push another object to another node events/wedding/packages right after this firebase database function above. I can use another function inside then callback in above firebase functions. This is not a professional way to do this.
Is there any way to do this?
You can use the update() method to "simultaneously write to specific children of a node without overwriting other child nodes". Note that "simultaneous updates made this way are atomic: either all updates succeed or all updates fails", see the doc.
So in your case you would do along the following lines:
var newNodeKey = firebase.database().ref().child('events/wedding/items').push().key;
var updates = {};
updates['events/wedding/items/' + newNodeKey] = { foo: "bar" };
updates['events/wedding/packages/' + newNodeKey] = { bar: "foo" };
firebase.database().ref().update(updates)
.then(() => {
// The two writes are completed, do whatever you need
// e.g. dispatch(...);
});
All Firebase operations return a promise so you can use Promise.all() to run them all simultaneously.
Promise.all([
firebase.database().ref(reference).set({}),
firebase.database().ref(reference2).set({})
]).then(() => {
console.log("Operations Successful")
}).catch((e) => console.log(e))
You can also push all your operations to an array and then pass that array in Promise.all()

Send event to array of child services in XState

I have a scenario where I have one parent machine and several child machines that can be spawned from the parent machine.
The current setup looks like this:
const parentMachine = Machine({
context: {
children: [] //can contain any number of child services
},
...
on: {
ADD_CHILD: {
actions: assign({
children: (ctx, e) => {
return [
...ctx.children,
{
ref: spawn(childMachine)
},
];
},
}),
},
UPDATE_CHILDREN: {
actions: ??? //need to somehow loop through children and send the UPDATE event to each service
}
}
});
When the parent machine receives the "UPDATE_CHILDREN" event, I want to update each of the child services. I know you can send batch events by passing an array to send, but I want each event to also be sent to a different service. I've only seen examples where they are sent to a single service at a time. I've tried several things, including the following:
UPDATE_CHILDREN: {
actions: ctx => ctx.children.forEach(c => send("UPDATE", { to: () => c.ref }) //doesn't send
}
Am I missing something obvious? Is this possible?
Ah, I bumped into exactly the same issue as you!
It turns out that if you give actions a function, it assumes the function to be the actual action, not a function that returns actions.
If you want to generate your actions based on context, you need to use a pure action:
import { actions } from 'xstate';
const { pure } = actions;
...
actions: pure((context, event) =>
context.myActors.map((myActor) =>
send('SOME_EVENT', { to: myActor })
)
),
This is a tricky mistake to fall into as you get no feedback that you're doing something wrong..
Had a realization about how this is supposed to work in XState.
The references to the children are already being stored, so we can just basically send events to them directly without using the "to" property:
actions: ctx => ctx.children.forEach(c => c.ref.send("UPDATE"))

Sequelize afterValidate hook called twice when updating

I'm using Sequelize in a Node backend to access a MySQL database and I realized that, depending on how you update an object, the afterValidate hook is called once or twice. I'll explain it better with an example:
We have a Shop entity defined by the following Sequelize model:
module.exports = (sequelize, DataTypes) => {
const Shop = sequelize.define('Shop', {
name: DataTypes.STRING,
address: DataTypes.STRING
}, {
freezeTableName: true,
hooks: {
afterValidate: (shop, options) => {
shop.name += '_HOOKED!'; // Just for testing
}
}
});
};
I've added a couple of shops using db.Shop.create() that have id 1 and 2. Now, I'm trying these 2 options that Sequelize provides to update a shop object:
Option 1
db.Shop.update({ name: 'Coffee Shop TEST' },
{ where: { id: shop.id } }).then((data) => {
console.log("All good!!");
}).catch((error) => {
console.log("No good: ", error);
});
Option 2
db.Shop.findOne({ where: { id: 1 } }).then((shop) => {
shop.update({ name: 'Coffee Shop TEST' }).then((data) => {
console.log("All good!!: ");
}).catch((error) => {
console.log("No good: ", error);
});
}).catch((error) => {
console.error("Error al actualizar: ", error);
});
If I use the first option, the shop is updated correctly and the afterValidate hook is called once, so the name now is: Coffee Shop TEST_HOOKED!.
However, if I use the second option, the hook is called twice so the name is set incorrectly to Coffee Shop TEST_HOOKED!_HOOKED!.
Why is this happening? Thanks in advance,
I might be a little late but for anyone who comes across this problem, here is the solution:
You can set options.validate = false in the beforeUpdate hook in your model.
For some reason, Sequelize runs the afterValidate hook twice when updating objects...
I tried to update an object that doesn't have any associations with other models and I got the same result: option 1 calls afterValidate hook once and option 2 calls it twice. Also, I tried to go back to sequelize version 5.1.0 and nothing changed.
So, it seems that sequelize works this way for whatever reason. I'll keep in mind that, if I want to update an object that has hooks on it, I'll use the code in option 1 to avoid problems like hashing the password twice.
Cheers,

GraphQL-subscriptions: How to get published object in subscription resolver

I am using an express server with GraphQL subscriptions and subscriptions-transport-ws.
I have set up the subscription with a given channel:
...
const subscriptionManager = new SubscriptionManager({
schema: executableSchema,
pubsub: pubsub,
setupFunctions: {
testRunChanged: (options, args) => {
return {
testRunChangedChannel: {
filter: (testRun) => {
return testRun.id === args.testRunId;
}
},
};
},
},
});
...
After a mutation is received a process is started on the server where the database entry of the test run is updated when finished. Now when the update promise for the database action passes the client should be informed.
Using the publish functionality from pubsub the subscription manager gets the information about the updated test run:
...
RunningTestDbService.setToFinished(testRun).then(updatedTestRun => {
pubsub.publish("testRunChangedChannel", updatedTestRun);
})
...
After the subscription manager filters the subscriptions depending on the published testRun and the subscribed testRunId the subscription resolver function is called. To update the client i have to fetch the updated test run again.
How can i get the published test run object inside of the subscription resolver function?
The subscription and the resolver look like this:
...
`testRunChanged(testRunId: ID!): TestRun!`
...
Subscription: {
testRunChanged(_, { testRunId }) {
// need to fetch the test run from database again
return TestRunDbService.getTestRunWith(testRunId);
},
},
...
The object used in publish method as payload is then root parameter of your subscription resolver method - so in this case this is _ in your testRunChanged resolver function. You should simply do return _.

Angular 2 Array Subject .next() not invoking another component's observer

I'm using firebase as my backend.
Inside of a data.service.ts, I create a Subject array which will be filled by the firebase observer on app init:
private orders = new Subject<any>();
orders$ = this.orders.asObservable();
firebase.database().ref(this.fbDataPath).on('child_added', (childSnapshot) => {
this.orders.next(
{
key: childSnapshot.key,
name: childSnapshot.val().name,
items: childSnapshot.val().items
}
)
})
I then provide a separate directory component with DataService and subscribe to its orders observable:
DataService.orders$.subscribe(
order => {
console.log('subscribe hit')
})
I can't seem to get the listener component to trigger on a next. I made this work for a boolean isLoggedIn, and I must be missing something in this scenario. Thanks!
It might be because you're using this in a closure. Remove the this from this.orders.next()

Categories