Console.log Refuses to Print Statements in Mutation File - node.js

I am using a PostgreSQL database, with a GraphQL / NodeJS server. One of the mutations is giving me extensive problems, due to its intrinsically complex nature. I am trying to use console.log statements throughout so I can track the data, but not a SINGLE statement prints. Now, before you all jump on me and say that the mutation probably isn't getting hit, that's not the case. I'm getting return values, the mutation is occurring (I checked the Network section of the Browser to confirm. I also have error handlers that do not get triggered) but nothing gets printed.
The code for one of the two mutations called simultaneously is as follows...
import db from "../../../../utils/generatePrisma.js";
import checkOwnerAuth from "../../../../utils/checkAuthorization/check-owner-auth.js";
import checkManagerAuth from "../../../../utils/checkAuthorization/check-manager-auth.js";
export default {
Mutation: {
scorecardToolCreateWeeklyReports: async (_, {
token,
dspId,
role,
transporterId,
date,
feedbackStatus,
feedbackMessage,
feedbackMessageSent,
rank,
tier,
delivered,
keyFocusArea,
fico,
seatbeltOffRate,
speedingEventRate,
distractionsRate,
followingDistanceRate,
signalViolationsRate,
deliveryCompletionRate,
deliveredAndRecieved,
photoOnDelivery,
attendedDeliveryAccuracy,
dnr,
podOpps,
ccOpps
}, context) => {
let owner;
let manager;
if (role === 'OWNER') {
owner = await checkOwnerAuth(token)
}
if (role === 'MANAGER') {
manager = await checkManagerAuth(token)
}
const foundDriver = await db.driver.findFirst({
where: {
transporterId: transporterId,
dspId: dspId
}
})
if (!foundDriver) {
throw new Error('Driver does not exist')
}
console.log("\n-----------------------\n Found Driver in scoreCardToolCreateWeeklyReport")
console.log(foundDriver)
try {
return await db.weeklyReport.create({
data: {
driver: {
connect: {
id: foundDriver.id
}
},
date: date,
feedbackStatus: feedbackStatus,
feedbackMessage: feedbackMessage,
feedbackMessageSent: feedbackMessageSent,
rank: rank,
tier: tier,
delivered: delivered,
keyFocusArea: keyFocusArea,
fico: fico,
seatbeltOffRate: seatbeltOffRate,
speedingEventRate: speedingEventRate,
distractionsRate: distractionsRate,
followingDistanceRate: followingDistanceRate,
signalViolationsRate: signalViolationsRate,
deliveryCompletionRate: deliveryCompletionRate,
deliveredAndRecieved: deliveredAndRecieved,
photoOnDelivery: photoOnDelivery,
attendedDeliveryAccuracy: attendedDeliveryAccuracy,
dnr: dnr,
podOpps: podOpps,
ccOpps: ccOpps
}
}).then( (resolved) => {
console.log(resolved)
})
} catch (error) {
console.log("\n---------------\n Error in WeeklyReportCreation")
console.log(error)
throw new Error(error)
}
}
}
}
Interestingly enough, the return I recieve is exactly what I would want and would expect, however, it does not persist, and on any refresh, rerender, or movement between pages and there's no model, its like the mutation just never even happened. When the mutation is called from the Frontend, it runs somewhat as expected. Upon hitting inspect on the browser and looking at the response section in the Network tab, I get the following...
{"data":
{"scorecardToolCreateWeeklyReports":
{"id":"91c7dd10-0af8-4fc7-9906-20643700c97f",
"createdAt":"2022-04-12T18:09:09.787Z",
"date":"11-24-22",
"hadAccident":false,
"feedbackMessage":"null",
"feedbackMessageSent":false,
"feedbackStatus":"Fantastic",
"acknowledged":false,
"acknowledgedAt":null,
"rank":1,
"tier":"Fantastic",
"delivered":116,
"keyFocusArea":"null",
"fico":"850",
"seatbeltOffRate":"Coming Soon",
"speedingEventRate":"Coming Soon",
"distractionsRate":"Coming Soon",
"followingDistanceRate":"Coming Soon",
"signalViolationsRate":"Coming Soon",
"deliveryCompletionRate":"100",
"deliveredAndRecieved":"100",
"photoOnDelivery":"100",
"attendedDeliveryAccuracy":0,
"dnr":0,
"podOpps":54,
"ccOpps":0,
"__typename":"WeeklyReport"}}}
The mutation shown before is then placed into a minor resolver...
import GraphQLJSON from "graphql-type-json";
import scorecardToolCreateDriverAccounts from "./mutations/scorecardToolCreateDriverAccounts.js";
import scorecardToolCreateWeeklyReports from "./mutations/scorecardToolCreateWeeklyReports.js";
export default {
Query: {
},
Mutation: {
...scorecardToolCreateDriverAccounts.Mutation,
...scorecardToolCreateWeeklyReports.Mutation
},
JSON: GraphQLJSON
}
And then this minor resolver is then imported into the main resolver
import GraphQLJSON from 'graphql-type-json';
// NEW RESOLVERS
import ownerReslovers from './owner/ownerResolvers.js';
import managerResolvers from './manager/managerResolvers.js';
import driverResolvers from './driver/driverResolvers.js';
import dspResolvers from './dsp/dspResolvers.js';
import weeklyReportResolvers from './weeklyReport/weeklyReportResolvers.js';
import scorecardResolvers from './scorecardTool/scorecardResolvers.js';
import chatroomResolvers from './chatrooms/chatroomResolvers.js';
import shiftPlannerResolvers from './shiftPlanner/shiftPlannerResolvers.js';
import messagesResolvers from './messages/messagesResolvers.js';
import accidentResolvers from './accidents/accidentResolvers.js';
import shiftPlannerDatesResolvers from './shiftPlannerDates/shiftPlannerDatesResolvers.js';
import shiftResolvers from './shift/shiftReolvers.js';
// ADDITIONAL RESOLVERS
import additionalResolvers from './additional/additionalResolvers.js';
export default {
Query: {
...ownerReslovers.Query,
...managerResolvers.Query,
...driverResolvers.Query,
...dspResolvers.Query,
...weeklyReportResolvers.Query,
...shiftPlannerResolvers.Query,
...chatroomResolvers.Query,
...messagesResolvers.Query,
...accidentResolvers.Query,
...shiftPlannerDatesResolvers.Query,
...shiftResolvers.Query,
...scorecardResolvers.Query,
...additionalResolvers.Query
},
Mutation: {
...ownerReslovers.Mutation,
...managerResolvers.Mutation,
...driverResolvers.Mutation,
...dspResolvers.Mutation,
...weeklyReportResolvers.Mutation,
...shiftPlannerResolvers.Mutation,
...chatroomResolvers.Mutation,
...messagesResolvers.Mutation,
...accidentResolvers.Mutation,
...shiftPlannerDatesResolvers.Mutation,
...shiftResolvers.Mutation,
...scorecardResolvers.Mutation,
...additionalResolvers.Mutation
},
JSON: GraphQLJSON,
}

It turns out my final thought was correct. The mutation is 100% being run, and the log statements are being hit.
The issue is due to AWS EC2 CodePipeline deployment. The backend server is perpetually being run on AWS's end, so the console where the logs occur is no longer my VSC terminal, but the instance's AWS console.
This is also the same with the front end, where if I run the code locally, none of the new logs get hit. I can only see ALL of the frontend logs if I am on the IP adress in the browser, not the localhost.
This all being said, I currently have no idea how to view the console in AWS and if anyone was privy to that information and cared to share that would be greatly appreciated

Related

Where do I check the debugging results of adonis api query?

I read the docs from here : https://docs.adonisjs.com/guides/database/debugging#pretty-print-queries
And I try like this :
import { HttpContextContract } from '#ioc:Adonis/Core/HttpContext'
import Database from '#ioc:Adonis/Lucid/Database'
import Event from '#ioc:Adonis/Core/Event'
export default class UsersController {
public async index({ params, response }: HttpContextContract) {
const results = await Database
.query()
.select('*')
.from('users as a')
.innerJoin('posts as b', 'a.id', 'b.user_id')
.groupBy('a.id')
Event.on('db:query', Database.prettyPrint)
return response.status(200).json({ code: 200, status: 'success', data: results })
}
}
I try using the pretty print queries like that and I call the query. Then I check on the terminal and postman too. But I don't find the result
Where do I check the debugging results of adonis api query?
Please help. Thanks
Inside file .adonisrc.json add preloads events value
{
"preloads": [
"./start/routes",
"./start/kernel",
"./start/events", // here
],
}
and create a new file start/events.js add example code as documented
import Event from '#ioc:Adonis/Core/Event'
import Database from '#ioc:Adonis/Lucid/Database'
import Logger from '#ioc:Adonis/Core/Logger'
import Application from '#ioc:Adonis/Core/Application'
Event.on('db:query', (query) => {
if (Application.inProduction) {
Logger.debug(query)
} else {
Database.prettyPrint(query)
}
})

Trying to retrieve Data from MongoDB using Typescript

Context: Am not too experienced with TypeScript, as we don't use it at work, am attempting to just build a little portfolio piece for personal exposure.
So to start with this is my code:
import { request, Request, Response } from 'express';
import { Neighborhood as NeighborhoodType } from '../interfaces/neighborhood.interface';
import Neighborhood from '../models/neighborhood';
const fetchNeighborhoods = async (request: Request, response: Response): Promise<void> => {
try {
const neighborhoods: NeighborhoodType[] = await Neighborhood.paginate();
response.status(200).send(neighborhoods);
} catch (error) {
throw error;
}
};
Am attempting to fetch the neighborhoods from the DB, and am receiving the error Type 'PaginateResult<Neighborhood>' is missing the following properties from type 'Neighborhood[]': length, pop, push, concat, and 26 more. on this line const neighborhoods: NeighborhoodType[] = await Neighborhood.paginate();
If I remove the NeighborhoodType[] then the method will work fine. The neighborhood interface is literally an object with a string.
export interface Neighborhood extends Document {
name: string,
}
Is it an issue with MY code or is it an issue with one of the dependencies?
For anyone who encounters this issue:
The problem stems from trying to set the return type. As Mongoose will always return one document, an array of documents or an empty array (unless using onFail()) the return type can be inferred so there is no need to add NeighborhoodType[].
The PaginateResult Type is essentially the type of Array if I'm not mistaken and is expecting the Neighborhood type to have all of the array methods which it will not.

Vue Electron stuck when calling some Node libraries asynchronously

Context
I'm trying to build an app using the following stack:
Vue.js
Electron
I've developed simple Vue apps for a while now and I understand the basics.
What I'm trying to do here is to combine Vue and Electron using this awesome tool: Vue CLI Plugin Electron Builder.
While I've successfully managed to code simple apps with this stack, I'm facing issues when it comes to exploit Electron's nodeIntegration which is supposed to give Node access directly to my Vue code.
Issue
My asynchronous calls to some methods of the systeminformation library seem to be stuck (sometimes).
That is, when I want to assign a value my view's data by calling an asynchronous method of the systeminformation library, Vue seems to hang and await indefinitely.
The weired thing is that, sometimes, when I force refresh the page, I can briefly see in my console the log supposed to be output when the method returns data.
It's almost like refreshing the page forces Vue or something else to update.
I'd suspect the following leads but I might be wrong:
Vue's reactivity issue in my way of declaring and/or assigning.
Node integration issue making Vue+Node not "bounded" properly.
Electron's packaging of a Node library missing configuration to be used in Vue "as if it was a regular JS library".
The latter point is unclear to me as I've always used Electron+Vue to access Node libraries the same way I'd do for web libraries.
There might more to it that could lead to these issues but this is as far as my knowledge goes...
Steps to reproduce
You can create a Vue+Electron as follows:
vue create myapp
vue add electron-builder
yarn add systeminformation
I'm leaving default values for Vue CLI's interactive project creation as they don't have an impact on my issue.
As per Vue CLI Plugin Electron Builder's documentation on nodeIntegration, my vue.config.js file looks like this:
module.exports = {
pluginOptions: {
electronBuilder: {
nodeIntegration: true,
},
},
};
You can then use the snippets in Scenario 1 and Scenario 2.
Scenario 1
Let's consider the following example where I assign a value using Axios:
<template>
<pre>{{ test }}</pre>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
test: null,
};
},
async mounted() {
console.log("Getting data from Axios...");
// Assign a value to the "test" data with an asynchronous HTTP call with Axios.
this.test = (
await axios.get("https://cat-fact.herokuapp.com/facts")
).data;
// It gets there as soon as the server responds.
console.log("Got it!", this.test);
},
};
</script>
Here, the asynchronous call works as expected, my test data updates properly and shows in my view as soon as the Axios call got an answer.
Scenario 2
Now, if I use the same logic to get my data from a method of the systeminformation library:
<template>
<pre>{{ test }}</pre>
</template>
<script>
import systeminformation from "systeminformation";
export default {
data() {
return {
test: null,
};
},
async mounted() {
console.log("Getting data from systeminformation...");
// Assign a value to the "test" data with an asynchronous call to a method of systeminformation.
this.test = await systeminformation.getStaticData();
// It just won't get there most of the time...
console.log("Got it!", this.test);
},
};
</script>
In that case, my view won't show the test data as Vue seems to hang on the systeminformation call indefinitely.
The console log won't even show as the await statement appears to make the mounted hook stuck.
I just tested systeminformation.getStaticData() function in my own Electron + Vue app and here's results:
It executes code asynchorously but the operation is so heavy, it makes the app almost completely unresponsive. It repeatedly spawns ~30 Node child processes effectively blocking 3-4 CPU threads.
I think it might be a bug with getStaticData() function. You might want to create a new issue in their repo and report it.
Solution
Either don't use this particular function and get all the needed info by running other systeminformation functions.
OR
Enable node integration in workers:
webPreferences: {
nodeIntegration: true,
nodeIntegrationInWorker: true
}
Execute this function in a worker, rather than on the main thread, and send the results back to your component, then terminate the worker. Though when you do this, open task manager and make sure it terminates all the spawned child processes with it:
Vue component
import sysInfoWorker from 'worker-loader!./workers/sysInfoWorker'
data () {
return {
sysInfoWorker: null
}
},
mounted () {
this.initSysInfoWorker()
},
methods: {
initSysInfoWorker () {
this.sysInfoWorker = new sysInfoWorker()
try {
this.sysInfoWorker.onmessage = (event) => {
console.log('sysInfoWorker message:', event)
this.test = event
}
this.sysInfoWorker.onerror = (error) => {
console.log('sysInfoWorker error:', error)
}
}
catch (error) {
console.log(error)
}
},
startSysInfoWorker () {
this.sysInfoWorker.postMessage({
operation: 'run:getStaticData'
})
},
cancelSysInfoWorker () {
this.sysInfoWorker.postMessage('cancel:getStaticData')
// this.sysInfoWorker.terminate()
}
}
Worker
const systeminformation = require('systeminformation')
const state = { cancelled: false }
// Listen to messages from parent thread
self.addEventListener('message', (event) => {
if (event.data === 'cancel:getStaticData') {
state.cancelled = true
}
else {
state.cancelled = false
initWorker(event)
}
})
async function initWorker (event) {
if (event.data.operation === 'run:getStaticData') {
const info = await systeminformation.getStaticData()
self.postMessage({ info: info })
}
}
If the worker throws errors, try adding the following to your vue.config:
module.exports = {
configureWebpack: {
module: {
rules: [
{
test: /\.worker\.js$/,
use: { loader: 'worker-loader' }
}

Using Nestjs to poll on DB Changes

I am looking for an option to use nest as a back-end Gateway service -
The idea is to poll on DB changes ( and maybe later to move it to event driven ) - de facto no listener would be required here.
On change the Nest would update a 3rd pt API calls
What would be best practice here ?
Take a look here, I'm doing something similar to what you're after: https://github.com/nerdybeast/sith-api/blob/feature/redis-cache/src/modules/api/sobjects/trace-flag/TraceFlagPoller.ts
I created a class that "polls" a backend and emits an event when it detects a change in that backend. You could have other code that listens for this event which makes the call to your 3rd party api.
UPDATE:
As you stated, Nest does have a basic application context which skips the http service setup, here's how you can do that:
index.ts
import { NestFactory } from '#nestjs/core';
import { ApplicationModule } from './ApplicationModule';
import { DatabaseService } from './DatabaseService';
(async () => {
const app = await NestFactory.createApplicationContext(ApplicationModule);
const databaseService = app.get<DatabaseService>(DatabaseService);
await databaseService.poll();
})();
DatabaseService.ts
#Injectable()
export class DatabaseService {
private expectedResult: any;
public async poll() : Promise<void> {
const result = await getData();
if(result !== this.expectedResult) {
this.expectedResult = result;
await axios.post('https://some-url.com', result);
}
//Poll every 5 seconds or whatever
setTimeout(() => this.poll(), 5000);
}
}
This could be the solution if you had to poll the database instead of being able to subscribe to it. With this approach, when you start the app, it will poll forever, constantly updating your 3rd party api.
I would start the index.ts file with pm2 or forever so that you can have a graceful restart if your process crashes for some reason.
I would personally use typeORM subscribers like I have done many times for similar requirements. However I use an eventEmitter to not block the saving action. This is a snippet of what I usually do.
#Injectable()
export class EntityUpdate implements EntitySubscriberInterface {
constructor(
#InjectConnection() readonly connection: Connection,
#InjectEventManager() emitter: AppEvents<AbstractEntity>,
) {
connection.subscribers.push(this);
}
afterInsert(event: InsertEvent<AbstractEntity>): void {
this.emitter('entity', {
method: 'update',
entity,
});
}
}
Then I could listen to the event anywhere within my application and handle that status change of the entity

Trying make a simple http get request in Angular Dart

I am learning front-end development in general with Angular Dart for a personal project (I've just learned back-end development with Django.) I get easily confused with the HTTP tutorial because from my perspective as a web developer beginner it tries to do a lot of things at the same time in different files or places and all related just for one purpose (it might be efficient to code that way, but I find hard learning from it.) I created an API for the project, and I want to know how to make a simple HTTP get request to build from there.
This is the JSON object that I'm trying to display:
"kanji": "老",
"onyomi": "ロウ",
"kunyomi": "お.いる、ふ.ける",
"nanori": "えび, おい, び",
"rtk_keyword": "old man",
"english": "old man, old age, grow old",
"jlpt": 3,
"jouyou_grade": "4",
"frequency": 803,
"radicals": [
2555,
2613
],
"pk": 1267
And this is my failed attempt at getting to display that data:
import "dart:async";
import 'dart:convert';
import 'package:angular2/angular2.dart';
import 'package:http/http.dart' as http;
import 'package:http/http.dart';
#Component (
selector: "test",
template: """
<button (click)="change_info()">{{info}}</button>
""",
)
class Test {
String info = "default info";
String _url = 'localhost:8000/kanji_detail/老';
String get_and_decode(String url) {
String data_to_return;
http.get(url).then((response) => data_to_return = JSON.decode(response.body));
return data_to_return;
}
String get_and_decode_long(String url) {
Response request_response;
Future request_future;
String data_to_return;
request_future = get(url);
request_future.then((response) => request_response = response);
data_to_return = JSON.decode(request_response.body);
return data_to_return;
}
change_info() {
info = get_and_decode_long(_url);
}
}
the get_and_decode_long is me understanding that a Future and a Response are involved in this process, it wasn't very obvious.
Future<String> get_and_decode(String url) async {
var response = await http.get(url);
return JSON.decode(response.body));
}
There is no way to get back from async to sync execution. async / await makes it quite easy to woek with async code though.
In your example return data_to_return; is executed before the response arrives.
See also
https://www.dartlang.org/tutorials/language/futures
https://www.dartlang.org/articles/language/await-async

Resources