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 _.
Related
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...
}
),
},
},
I have some queries from an API-Server that returns a json object that will be static over a user session, but not static forever.
It's a one-pager with Vue router.
How can I achieve that I:
can access this.myGlobals (or similar eg window.myGlobals) in all components, where my prefetched json-data from API-Server is stored.
My approach that is already working is to embed help.js via a mixin.
Oddly enough, I get hundreds of calls to this query. At first I thought that it only happened in the frontend and is chached, but the requests are actually sent hundreds of times to the server. I think it is a mistake of my thinking, or a systematic mistake.
i think the problem is, that the helper.js is not static living on the vue instance
main.js:
import helpers from './helpers'
Vue.mixin(helpers)
helpers.js:
export default {
data: function () {
return {
globals: {},
}
}, methods: {
//some global helper funktions
},
}, mounted() {
let url1 = window.datahost + "/myDataToStore"
this.$http.get(url1).then(response => {
console.log("call")
this.globals.myData = response.data
});
}
}
log in console:
call
SomeOtherStuff
(31) call
SomeOtherStuff
(2) call
....
log on server:
call
call
call (pew pew)
My next idea would be to learn vuex, but since its a easy problem, im not sure if i really need that bomb ?
You can use plugin to achieve this.
// my-plugin.js
export default {
install (Vue, options) {
// start fetching data right after install
let url1 = window.datahost + "/myDataToStore"
let myData
Vue.$http.get(url1).then(response => {
console.log("call")
myData = response.data
})
// inject via global mixin
Vue.mixin({
computed: {
myData () {
return myData
}
}
})
// or inject via instance property
Vue.prototype.$myData = myData
// or if you want to wait until myData is available
Vue.prototype.$myData = Vue.$http.get(url1)
.then(response => {
console.log("call")
myData = response.data
})
}
}
and use it:
Vue.use(VueResource)
Vue.use(myPlugin)
I have a local Java Service that exposes a single endpoint where the response can take over 5min sometimes depending on the request size. I want to "hide" this endpoint behind Strapi, so that a user that is not authenticated through Strapi, can't access this endpoint. What i've done is, created a custom Route in Strapi, and created a custom controller function for this route:
async optimizeRoute(ctx) {
try {
console.log(`${new Date()} - Optimize route started`)
const vehicles = ctx.request.body.vehicles.map(vehicle => {
return {
id: vehicle.id,
licenseplate: vehicle.licenseplate,
maxweight: vehicle.maxweight,
maxlength: vehicle.maxlength,
geojson: vehicle.geojson,
maxtime: moment(vehicle.endtime).diff(moment(vehicle.starttime), 'seconds') * 1.1
}
});
const orders = ctx.request.body.orders.map(order => {
return {
id: order.id,
weight: order.weight,
length: order.length,
geojson: order.geojson
}
});
console.log(`Using ${vehicles.length} vehicles, and ${orders.length} orders!`)
const response = await axios.post('http://127.0.0.1:9090/optimizeroutes',
{ vehicles: vehicles, orders: orders }, {timeout: 0}
);
return response.data;
} catch (error) {
ctx.throw(error.response.status, error.response);
}
}
But what happens when i do this, is Strapi closes the connection after 1-2 min to the requester before the response is returned.
Using Strapi Beta3.17.5.
Anywhere i can configure or debug to wait for the axios to return a response then return the response to the requester??
The default server timeout value is 2 min, Please check the image for reference.
So in server.js you can increase this timeout value by passing callback function
So the code will look like below
const strapi = require('strapi');
strapi(/* {...} */).start(()=>{
strapi.server.setTimeout(0);
});
setting timeout to 0 strapi will wait forever or you can add value in milliseconds.
Thank you for putting me on the right track #NS23, but i couldn't user server.js to start my server, and console logging strapi.server returned undefined.
What i did though was access strapi.server in Bootstrap.js, which then logging strapi.server, could see the timeout was changed from 120000 to 0
Sentry by defaults has integration for console.log to make it part of breadcrumbs:
Link: Import name: Sentry.Integrations.Console
How can we make it to work for bunyan logger as well, like:
const koa = require('koa');
const app = new koa();
const bunyan = require('bunyan');
const log = bunyan.createLogger({
name: 'app',
..... other settings go here ....
});
const Sentry = require('#sentry/node');
Sentry.init({
dsn: MY_DSN_HERE,
integrations: integrations => {
// should anything be handled here & how?
return [...integrations];
},
release: 'xxxx-xx-xx'
});
app.on('error', (err) => {
Sentry.captureException(err);
});
// I am trying all to be part of sentry breadcrumbs
// but only console.log('foo'); is working
console.log('foo');
log.info('bar');
log.warn('baz');
log.debug('any');
log.error('many');
throw new Error('help!');
P.S. I have already tried bunyan-sentry-stream but no success with #sentry/node, it just pushes entries instead of treating them as breadcrumbs.
Bunyan supports custom streams, and those streams are just function calls. See https://github.com/trentm/node-bunyan#streams
Below is an example custom stream that simply writes to the console. It would be straight forward to use this example to instead write to the Sentry module, likely calling Sentry.addBreadcrumb({}) or similar function.
Please note though that the variable record in my example below is a JSON string, so you would likely want to parse it to get the log level, message, and other data out of it for submission to Sentry.
{
level: 'debug',
stream:
(function () {
return {
write: function(record) {
console.log('Hello: ' + record);
}
}
})()
}
I am trying to implement a search function where a user can return other users by passing a username through a component. I followed the ember guides and have the following code to do so in my routes file:
import Ember from 'ember';
export default Ember.Route.extend({
flashMessages: Ember.inject.service(),
actions: {
searchAccount (params) {
// let accounts = this.get('store').peekAll('account');
// let account = accounts.filterBy('user_name', params.userName);
// console.log(account);
this.get('store').peekAll('account')
.then((accounts) => {
return accounts.filterBy('user_name', params.userName);
})
.then((account) => {
console.log(account);
this.get('flashMessages')
.success('account retrieved');
})
.catch(() => {
this.get('flashMessages')
.danger('There was a problem. Please try again.');
});
}
}
});
This code, however, throws me the following error:
"You cannot pass '[object Object]' as id to the store's find method"
I think that this implementation of the .find method is no longer valid, and I need to go about returning the object in a different manner. How would I go about doing this?
You can't do .then for filterBy.
You can't do .then for peekAll. because both will not return the Promise.
Calling asynchronous code and inside the searchAccount and returning the result doesn't make much sense here. since searchAccount will return quickly before completion of async code.
this.get('store').findAll('account',{reload:true}).then((accounts) =>{
if(accounts.findBy('user_name', params.userName)){
// show exists message
} else {
//show does not exist message
}
});
the above code will contact the server, and get all the result and then do findBy for the filtering. so filtering is done in client side. instead of this you can do query,
this.store.query('account', { filter: { user_name: params.userName } }).then(accounts =>{
//you can check with length accounts.length>0
//or you accounts.get('firstObject').get('user_name') === params.userName
//show success message appropriately.
});
DS.Store#find is not a valid method in modern versions of Ember Data. If the users are already in the store, you can peek and filter them:
this.store.peekAll('account').filterBy('user_name', params.userName);
Otherwise, you'll need to use the same approach you used in your earlier question, and query them (assuming your backend supports filtering):
this.store.query('account', { filter: { user_name: params.userName } });