Showing posts with label asynchronous. Show all posts
Showing posts with label asynchronous. Show all posts

Monday, September 3, 2018

Is there any way to wait for a Dom to be updated or asynchronously update the Dom?

Leave a Comment

I have a simple loading bar made with css, you update the css and the bar fills, super simple. I decided to update the bar with jQuery, works great but now I throw it into a practical environment. I have a bunch of files being downloaded and each time a file successfully downloads, it updates the position. The main problem is that it downloads the files so fast, and places the files correctly fast enough that it just doesn't update the loading bar unless I set a timeout interval of 300-400ms..it does log into console and I made an interval function that continously checks to see if a file is finished based on a global variable. No matter where I place the function to update the loading bar or how I update it, it seems the Dom will not react unless there's a big enough delay between files OR it will react at the very end (jumps to 100).

Is there any way to wait for a Dom to be updated by J's OR can you spot a problem in my code that causes this issue?

I also tried promises too but it didn't change how the browser reacts to the function.

This is all being done inside a Cordova environment but I tested it on chrome too and it works as long as the pc is powerful enough it seems.

The file Transfer function has an "on Success" too but that doesn't do anything as the Dom wont update in it until after all the downloads are done OR there's a delay

My solutions so far is to either intentionally lag the downloader, or lag it every 10 or 20 files to update the position

Edit: here's my loading bar Js

  var colorInc = 100 / 3;   function setWater(myval)   {    var val = myval; var waitForMe = $.Deferred();   if(val != ""   && !isNaN(val)   && val <= 100   && val >= 0) {   setTimeout(function(){waitForMe.resolve()}, 100);   var valOrig = val;   val = 100 - val;    if(valOrig == 0)   {     //$("#percent-box").val(0);     $(".progress .percent").text(0 + "%");   }   else $(".progress .percent").text(valOrig + "%");    $(".progress").parent().removeClass();   $(".progress .water").css("top", val + "%");    if(valOrig < colorInc * 1)     $(".progress").parent().addClass("red");   else if(valOrig < colorInc * 2)     $(".progress").parent().addClass("orange");   else     $(".progress").parent().addClass("green"); } else {   setTimeout(function(){waitForMe.resolve()}, 100);   $(".progress").parent().removeClass();   $(".progress").parent().addClass("green");   $(".progress .water").css("top", 100 - 67 + "%");   $(".progress .percent").text(67 + "%");   //$("#percent-box").val(""); } return waitForMe.promise();    }; 

Dowload tracker:

 var DLProgress = null;  function updateProgress() {   var oldNum = 0;   DLProgress = setInterval(function(){     if(!doneArts) {        doneArts = true;    downloadHelper("Articles",articleSize,33.33,0);    }else if(currPos >= totalSize - 1){    clearInterval(DLProgress);    goNews();     currPos = 0;    doneArticles = false;     doneJson = false;    doneArts = false;    } else if(currPos >= articleSize && !doneArticles) {     doneArticles = true;    downloadHelper("json",jsonSize,33.33,33.33);     } else if(currPos >= articleSize + jsonSize && !doneJson) {     doneJson = true;      downloadHelper("img",imgSize,33.33,66.66);      }       if(oldNum != currPos) {       oldNum = currPos;       setWater(Math.ceil(100 * currPos / totalSize));      }      },5);     } 

Download Helper :

 function downloadHelper(name,size,maxPerc,startingPoint) {  dataFiles[name].forEach(function(file){    var getItem = localStorage.getItem(name+"/"+file[0]) || null; //might not work    if(getItem === null || getItem !== file[1]) {    //download file.     if(file[0] !== null && file[1] !== null) {       //setWater(Math.ceil(100 * currPos / totalSize)).done(function(){downloader(name+"/"+file[0],file[1]);});       setTimeout(function(){downloader(name+"/"+file[0],file[1])},window.dltime);       window.dltime += 200;     }    }   });  }; 

File transfer used : https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file-transfer/

It Does update after each download helper has finished

Is there any way to wait for a Dom to be updated by J's OR can you spot a problem in my code that causes this issue?

2 Answers

Answers 1

I think you have the case with the variable currPos. Use debug tool to mark the lines and inspect value of currPos. Somehow your code is managed to jump it 0 to articleSize.

Answers 2

The DOM is updated each time the download is completed - it could be a problem.
We should separate upload progress and animation. When file is downloaded you should just change some kind of Model and use requestAnimationFrame recursively to animate a progress bar.

requestAnimationFrame is called 60 times per second, but will generally match the display refresh rate, paused in most browsers when running in background tabs or hidden <iframe>s in order to improve performance and battery life.

Read More

Sunday, August 12, 2018

@Async not working in Spring API rest with Interfaces

Leave a Comment

I'm working with @Async to stored some data in parallel in the database with hibernate. I need to do that because before saving the information to the database I need to run some task that takes several minutes. So I implemented @Async.

The issue is that @Async seems to not be working. Please find the code below:

WebConfig

@Configuration @EnableAsync @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter {  } 

StudentServiceImpl:

@Autowired RunSomeTaskService runSomeTaskService;  @Override Transactional public Response saveWithoutWaiting(StudentBO[] students, String username) throws Exception { ... for (StudentBO student : students) {     ....     Future<Response> response = runSomeTaskService.doTasks(student);     //Finish without waiting for doTasks(). }  @Override     Transactional     public Response saveWithWaiting(StudentBO[] students, String username) throws Exception {     ...     for (StudentBO student : students) {         ....         Future<Response> response = runSomeTaskService.doTasks(student);         //Finish and wait for doTasks().         response.get();     } 

RunSomeTaskService:

public interface RunSomeTaskService{     @Async     public Future<Response> doTasks(Student student); } 

RunSomeTaskServiceImpl:

public class RunSomeTaskServiceImpl extends CommonService implements RunSomeTaskService{  Student student; @Override     public Future<Response> doTasks(Student student) {           Response response = new Response();           this.student = student;           //do Task           return new AsyncResult<Response>(response);        } } 

web.xml

<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee            http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"     version="3.0">      <display-name>Sample Spring Maven Project</display-name>      <servlet>         <servlet-name>mvc-dispatcher</servlet-name>         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>         <init-param>             <param-name>contextConfigLocation</param-name>             <param-value>/WEB-INF/spring-config.xml</param-value>         </init-param>         <load-on-startup>1</load-on-startup>         <async-supported>true</async-supported>     </servlet>      <servlet-mapping>         <servlet-name>mvc-dispatcher</servlet-name>         <url-pattern>/</url-pattern>     </servlet-mapping>  <filter>     <filter-name>encodingFilter</filter-name>     <filter-class>             org.springframework.web.filter.CharacterEncodingFilter         </filter-class>     <init-param>       <param-name>encoding</param-name>       <param-value>UTF-8</param-value>     </init-param>   </filter>   <filter-mapping>     <filter-name>encodingFilter</filter-name>     <url-pattern>/*</url-pattern>   </filter-mapping>   <filter>     <filter-name>jwtTokenAuthFilter</filter-name>     <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>   </filter>   <filter-mapping>     <filter-name>jwtTokenAuthFilter</filter-name>     <url-pattern>/*</url-pattern>   </filter-mapping> </web-app> 

spring.config.xml

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"     xmlns:util="http://www.springframework.org/schema/util"      xmlns:mvc="http://www.springframework.org/schema/mvc"     xmlns:tx="http://www.springframework.org/schema/tx"     xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd   http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd   http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd   http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd   http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">      <context:annotation-config  />     <context:component-scan base-package="com.app.controller" />     <tx:annotation-driven transaction-manager="transactionManager"/>     <mvc:annotation-driven />      <bean id="dataSource"         class="org.springframework.jdbc.datasource.DriverManagerDataSource">         ...     </bean>      <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> ...     </bean>       <bean id="sessionFactory"         class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">         <property name="dataSource" ref="dataSource" />         <property name="annotatedClasses">             <list>                 <value>//every model generated with Hibernate</value>             </list>         </property>         <property name="hibernateProperties">             <props>                 <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>                 <prop key="hibernate.show_sql">true</prop>             </props>         </property>     </bean>      <bean id="transactionManager"         class="org.springframework.orm.hibernate5.HibernateTransactionManager">         <property name="sessionFactory" ref="sessionFactory" />     </bean>      <bean id="persistenceExceptionTranslationPostProcessor"         class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />      <bean id="studentService" class="com.app.services.StudentServiceImpl"></bean>     <bean id="studentDao" class="com.app.dao.StudentDaoImpl"></bean>     ...      <bean id="jwtTokenAuthFilter" class="com.app.security.JWTTokenAuthFilter" />        </beans> 

So, could you please help me to understand why @Async is not working?

5 Answers

Answers 1

Here you find the solutions

// servlet.setAsyncSupported(true);

//For Example

public class WebAppInitializer implements WebApplicationInitializer {     @Override     public void onStartup(ServletContext servletContext) throws ServletException {         AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();         ctx.register(WebConfig.class);         ctx.setServletContext(servletContext);         ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher",             new DispatcherServlet(ctx));         servlet.setLoadOnStartup(1);         servlet.addMapping("/");         servlet.setAsyncSupported(true); //Servlets were marked as supporting async         // For CORS Pre Filght Request         servlet.setInitParameter("dispatchOptionsRequest", "true");     } } 

Answers 2

Well, finally I make it work...

I used Executors in the following way:

ExecutorService executor = Executors.newFixedThreadPool(students.size()); for (StudentBO student : students) {     executor.submit(() -> extractDataService.doTask(student)); } 

Where doTask is a regular function, that when I don't need it to work in a different thread, I just call it as it is. When I need the threads, I use the code above.

Answers 3

More Sophisticated way would be to implement AsyncConfigurer and set the AsyncExecutor to threadPoolTaskExecutor.

Sample Code below

@Configuration @EnableAsync(proxyTargetClass=true) //detects @Async annotation public class AsyncConfig implements AsyncConfigurer {   public Executor threadPoolTaskExecutor() {         ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();         executor.setCorePoolSize(10); // create 10 Threads at the time of initialization         executor.setQueueCapacity(10); // queue capacity         executor.setMaxPoolSize(25); // if queue is full, then it will create new thread and go till 25         executor.setThreadNamePrefix("DEMO-");         executor.initialize();//Set up the ExecutorService.         return executor;     }      @Override     public Executor getAsyncExecutor() {         return threadPoolTaskExecutor();     }      @Override     public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {         return new YOUR_CUSTOM_EXCEPTION_HANDLER();     }  }  

The above configuration will detect @Async annotation wherever mentioned

Answers 4

You can do CompletableFuture , with this you know when all your tasks are complete

List<CompletableFuture<T>> futureList = new ArrayList<>();  for(Student student:studentList){  CompletableFuture<T> returnedFuture = CompletableFuture.supplyAsync(() -> doSomething(student),executor).exceptionally(e -> {         log.error("Error occured in print something future",e);         return 0;     });  futureList.add(returnedFuture); }  Completable.allOf(futureList); 

Then you can pipeline with thenCompose or thenApply (to take consumer) to have complete control on the task pipeline. you can shutdonw executors when you are done safely.

CompletetableFuture.allOff javadoc for more info

Answers 5

There is possibility that the @EnableAsync annotation in WebConfig.java is never scanned. The web.xml points to the spring-context.xml.

You can change the DispatcherServlet definition in web.xml to:

<servlet>     <servlet-name>mvc-dispatcher</servlet-name>     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>     <init-param>         <param-name>contextClass</param-name>         <param-value>             org.springframework.web.context.support.AnnotationConfigWebApplicationContext         </param-value>     </init-param>     <init-param>         <param-name>contextConfigLocation</param-name>         <param-value>             com.yourpackage.WebConfig         </param-value>     </init-param>     <load-on-startup>1</load-on-startup>     <async-supported>true</async-supported> </servlet> 

And include all configuration from spring-config.xml to this class.

Or Add <task:annotation-driven> in spring-config.xml.

Updated

Currently, com.app.controller package is scanned in spring-config.xml. Make sure the WebConfig.java is in this package or one of it's sub-package. If not add WebConfig's package to base package attribute separated by comma.

Additionally, you can control the thread pool used by async task. Create a executor bean

@Bean public Executor asyncTaskExecutor() {     ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();     executor.setCorePoolSize(5);     executor.setMaxPoolSize(10);     executor.setThreadNamePrefix("asynctaskpool-");     executor.initialize();     return executor; }  

And in your async method use the bean name like this

@Async("asyncTaskExecutor") public Future<Response> doTasks(Student student); 

This will ensure all task will be executed in this thread pool.

Read More

Sunday, July 29, 2018

Redirecting to another page prevents functions from returning their values

Leave a Comment

I have a Login page and if user logs in I want to redirect the user to another HTML page where I will list users tasks that I get from server.

The problem is:

Even though the functions I wrote works properly and backend API returns the values I want (I can see the value details on Console) when I use redirect code $window.location.href = '../Kullanici/userPanel.html the page redirects immedietly after login and for some reason I can't use the values returned by functions after redirection. Not only that I can't see the details of the value returned on console log anymore.

And here is my code for it:

Controller:

app.controller('myCtrl', ['$scope', '$http', '$window','$mdToast', 'userTaskList',     function ($scope, $http, $window, $mdToast, userTaskList) {         $scope.siteLogin = function () {              var userName = $scope.panel.loginUserName;             var password = $scope.panel.loginPassword;             var loginMember = { //JSON data from login form                 K_ADI: $scope.panel.loginUserName,                 PAROLA: $scope.panel.loginPassword             };             $http({                 method: 'POST',                 url: 'http://localhost:5169/api/Kullanicilar/KullaniciDogrula',                 headers: {                     'Content-Type': 'application/json'                 },                 data: loginMember              }).then(function successCallback(response) {                  console.log("message sent", response);                 $scope.data = response.data.error.data;                 if ($scope.data === true) {//if username and password is correct                      console.log("User exists");                     userTaskList.showActiveTasks(userName)                         .then(function (activeTaskResponse) {                             var activeTasks = activeTaskResponse;                             console.log("Active tasks (controller): ", activeTaskResponse);                              userTaskList.showFinishedTasks(userName)                                 .then(function (finishedTaskResponse) {                                     var finishedTasks = finishedTaskResponse;                                     console.log("Finished tasks(controller): ", finishedTaskResponse);                                     $scope.getMessage();                                     $window.location.href = '../Kullanici/userPanel.html';                                 }, function (err) {                                     console.log(err);                                 });                          }, function (err) {                             console.log(err);                         });                  }              }, function errorCallback(response) {                 console.log("Couldn't send", response);             });         } 

So what causes this problem and how can I fix it?

Edit: I nested .then parts but it doesnt work properly and gives This value was just evaluated now warning. So I stil can't use data on the redirected HTML page.

I also removed the factory since it makes the code look really messy and its probably not the source of the problem.

2 Answers

Answers 1

I would have nested the your two functions inside the first promise, then redirect once all of them are done. Something like

app.controller('myCtrl', ['$scope', '$http', '$window','$mdToast', 'userTaskList',   function ($scope, $http, $window, $mdToast, userTaskList) {     $scope.siteLogin = function () {          var userName = $scope.panel.loginUserName;         var password = $scope.panel.loginPassword;         var loginMember = { //JSON data from login form             K_ADI: $scope.panel.loginUserName,             PAROLA: $scope.panel.loginPassword         };          $http({             method: 'POST',             url: 'http://localhost:5169/api/Kullanicilar/KullaniciDogrula',             headers: {                 'Content-Type': 'application/json'             },             data: loginMember          }).then(function successCallback(response) {              console.log("message sent", response);             $scope.data = response.data.error.data;             if ($scope.data === true) {//if username and password is correct                  console.log("User exists");                 userTaskList.showActiveTasks(userName)                     .then(function (res) {                         var activeTasks = res;                         console.log("Active tasks (controller): ", res);                          userTaskList.showFinishedTasks(userName)                         .then(function (res) {                             var finishedTasks = res;                             console.log("Finished tasks(controller): ", res);                             $scope.getMessage();                              $window.location.href = '../Kullanici/userPanel.html';                         }, function (err) {                             console.log(err);                         });                      }, function (err) {                         console.log(err);                     });              } else { //if username or password is wrong                 $mdToast.show(                     $mdToast.simple()                         .textContent('Username or Password is wrong')                         .position('right')                         .hideDelay(3000)                             );                   }          }, function errorCallback(response) {             console.log("Couldn't send", response);         });                }    } ]); 

Answers 2

Oh I injected ngRoute to my AngularJS module but haven't use it yet.

Using $window.location.href kills the app and loads the other page, losing $rootScope, $scope, and all service data.

Re-factor your code to use a router and store the data in a service:

$routeProvider  .when('/userPanel' , {      templateUrl: 'partials/userPanel.html',      controller: panelController }) 
 panelService.set(data);  $location.path("/userPanel.html");      

OR use localStorage to store the data:

 localStorage.setItem('panelData', JSON.stringify(data));  $window.location.href = '../Kullanici/userPanel.html'; 

Data stored in a service will survive route changes (which destroy $scope). Data stored in localStorage will survive page changes (which destroy apps).


The code can be simplified

This will solve the problem of having the page wait for the data before changing the route.

Since the getMessages function makes an HTTP request it needs to be modified to return a promise:

$scope.getMessages = getMessages; function getMessages() {     return $http({         method: 'GET',         url: 'http://localhost:5169/api/chat/chatCek'     }).then(function successCallback(res) {         console.log("Mesajlar", res);         $scope.messages = res.data.error.data;         return res.data.error.data;     }, function errorCallback(res) {         console.log("Hata", res);         throw res;     }); } 

Then to delay the changing of the route until the getMessages data returns from the server, chain from the getMessages promise:

$http({     method: 'POST',     url: 'http://localhost:5169/api/Kullanicilar/KullaniciDogrula',     data: loginMember }).   then(function successCallback(response) {     console.log("message sent", response);     $scope.data = response.data.error.data;     if ($scope.data !== true) { throw "user error" };     //username and password is correct     console.log("User exists");     return userTaskList.showActiveTasks(userName); }).   then(function (activeTaskResponse) {     var activeTasks = activeTaskResponse;     console.log("Active tasks (controller): ", activeTaskResponse);     return userTaskList.showFinishedTasks(userName) }).   then(function (finishedTaskResponse) {     var finishedTasks = finishedTaskResponse;     console.log("Finished tasks(controller): ", finishedTaskResponse);     //CHAIN from getMessages promise     return $scope.getMessages(); }).   then(function(data) {     console.log(data);     //SAVE data before changing route     panelService.set(data);     $location.path( "/userPanel" );     //OR STORE data before changing app     //localStorage.setItem('panelData', JSON.stringify(data));                  //$window.location.href = '../Kullanici/userPanel.html'; }).   catch(function (response) {     console.log("Couldn't send", response);     throw response; }); 
Read More

Friday, December 22, 2017

How to mock an asynchronous function call in another class

Leave a Comment

I have the following (simplified) React component.

class SalesView extends Component<{}, State> {   state: State = {     salesData: null   };    componentDidMount() {     this.fetchSalesData();   }    render() {     if (this.state.salesData) {       return <SalesChart salesData={this.state.salesData} />;     } else {       return <p>Loading</p>;     }   }    async fetchSalesData() {     let data = await new SalesService().fetchSalesData();     this.setState({ salesData: data });   } } 

When mounting, I fetch data from an API, which I have abstracted away in a class called SalesService. This class I want to mock, and for the method fetchSalesData I want to specify the return data (in a promise).

This is more or less how I want my test case to look like:

  • predefine test data
  • import SalesView
  • mock SalesService
  • setup mockSalesService to return a promise that returns the predefined test data when resolved

  • create the component

  • await
  • check snapshot

Testing the looks of SalesChart is not part of this question, I hope to solve that using Enzyme. I have been trying dozens of things to mock this asynchronous call, but I cannot seem to get this mocked properly. I have found the following examples of Jest mocking online, but they do not seem to cover this basic usage.

My questions are:

  • How should the mock class look like?
  • Where should I place this mock class?
  • How should I import this mock class?
  • How do I tell that this mock class replaces the real class?
  • How do set up the mock implementation of a specific function of the mock class?
  • How do I wait in the test case for the promise to be resolved?

One example that I have that does not work is given below. The test runner crashes with the error throw err; and the last line in the stack trace is at process._tickCallback (internal/process/next_tick.js:188:7)

# __tests__/SalesView-test.js import React from 'react'; import SalesView from '../SalesView';  jest.mock('../SalesService'); const salesServiceMock = require('../SalesService').default;  const weekTestData = [];  test('SalesView shows chart after SalesService returns data', async () => {   salesServiceMock.fetchSalesData.mockImplementation(() => {     console.log('Mock is called');     return new Promise((resolve) => {       process.nextTick(() => resolve(weekTestData));     });   });    const wrapper = await shallow(<SalesView/>);   expect(wrapper).toMatchSnapshot(); }); 

3 Answers

Answers 1

Sometimes, when a test is hard to write, it is trying to tell us that we have a design problem.

I think a small refactor could make things a lot easier - make SalesService a collaborator instead of an internal.

By that I mean, instead of calling new SalesService() inside your component, accept the sales service as a prop by the calling code. If you do that, then the calling code can also be your test, in which case all you need to do is mock the SalesService itself, and return whatever you want (using sinon or any other mocking library, or even just creating a hand rolled stub).

Answers 2

One "ugly" way I've used in the past is to do a sort of poor-man's dependency injection.

It's based on the fact that you might not really want to go about instantiating SalesService every time you need it, but rather you want to hold a single instance per application, which everybody uses. In my case, SalesService required some initial configuration which I didn't want to repeat every time.[1]

So what I did was have a services.ts file which looks like this:

/// In services.ts let salesService: SalesService|null = null; export function setSalesService(s: SalesService) {     salesService = s; } export function getSalesService() {     if(salesService == null) throw new Error('Bad stuff');     return salesService; } 

Then, in my application's index.tsx or some similar place I'd have:

/// In index.tsx // initialize stuff const salesService = new SalesService(/* initialization parameters */) services.setSalesService(salesService); // other initialization, including calls to React.render etc. 

In the components you can then just use getSalesService to get a reference to the one SalesService instance per application.

When it comes time to test, you just need to do some setup in your mocha (or whatever) before or beforeEach handlers to call setSalesService with a mock object.

Now, ideally, you'd want to pass in SalesService as a prop to your component, because it is an input to it, and by using getSalesService you're hiding this dependency and possibly causing you grief down the road. But if you need it in a very nested component, or if you're using a router or somesuch, it's becomes quite unwieldy to pass it as a prop.

You might also get away with using something like context, to keep everything inside React as it were.

The "ideal" solution for this would be something like dependency injection, but that's not an option with React AFAIK.


[1] It can also help in providing a single point for serializing remote-service calls, which might be needed at some point.

Answers 3

You could potentially abstract the new keyword away using a SalesService.create() method, then use jest.spyOn(object, methodName) to mock the implementation.

import SalesService from '../SalesService ';  test('SalesView shows chart after SalesService returns data', async () => {      const mockSalesService = {         fetchSalesData: jest.fn(() => {             return new Promise((resolve) => {                 process.nextTick(() => resolve(weekTestData));             });         })     };      const spy = jest.spyOn(SalesService, 'create').mockImplementation(() => mockSalesService);      const wrapper = await shallow(<SalesView />);     expect(wrapper).toMatchSnapshot();     expect(spy).toHaveBeenCalled();     expect(mockSalesService.fetchSalesData).toHaveBeenCalled();      spy.mockReset();     spy.mockRestore(); }); 
Read More

Thursday, September 7, 2017

Using ExecuteNonQueryAsync and Reporting Progress

Leave a Comment

I thought I was trying to do something very simple. I just want to report a running number on the screen so the user gets the idea that the SQL Stored Procedure that I'm executing is working and that they don't get impatient and start clicking buttons.

The problem is that I can't figure out how to actually call the progress reporter for the ExecutNonQueryAsync command. It gets stuck in my reporting loop and never executes the command but, if I put it after the async command, it will get executed and result will never not equal zero.

Any thoughts, comments, ideas would be appreciated. Thank you so much!

        int i = 0;         lblProcessing.Text = "Transactions " + i.ToString();         int result = 0;         while (result==0)         {             i++;             if (i % 500 == 0)             {                 lblProcessing.Text = "Transactions " + i.ToString();                 lblProcessing.Refresh();             }          }         //  Yes - I know - the code never gets here - that is the problem!          result = await cmd.ExecuteNonQueryAsync(); 

5 Answers

Answers 1

Do you just want to let the user know that something is happening, and you don't actually need to display current progress?

If so, you could just display a ProgressBar with its Style set to Marquee.

If you want this to be a "self-contained" method, you could display the progress bar on a modal form, and include the form code in the method itself.

E.g.

public void ExecuteNonQueryWithProgress(SqlCommand cmd) {     Form f = new Form() {         Text = "Please wait...",         Size = new Size(400, 100),         StartPosition = FormStartPosition.CenterScreen,         FormBorderStyle = FormBorderStyle.FixedDialog,         MaximizeBox = false,         ControlBox = false     };     f.Controls.Add(new ProgressBar() {          Style = ProgressBarStyle.Marquee,         Dock = DockStyle.Fill     });     f.Shown += async (sender, e) => {         await cmd.ExecuteNonQueryAsync();         f.Close();     };     f.ShowDialog(); } 

Answers 2

You're not going to be able to get ExecuteNonQueryAsync to do what you want here. To do what you're looking for, the result of the method would have to be either row by row or in chunks incremented during the SQL call, but that's not how submitting a query batch to SQL Server works or really how you would want it to work from an overhead perspective. You hand a SQL statement to the server and after it is finished processing the statement, it returns the total number of rows affected by the statement.

Answers 3

The simplest way to do this is to use a second connection to monitor the progress, and report on it. Here's a little sample to get you started:

using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; using System.Text; using System.Threading.Tasks;  namespace Microsoft.Samples.SqlServer {     public class SessionStats     {         public long Reads { get; set; }         public long Writes { get; set; }         public long CpuTime { get; set; }         public long RowCount { get; set; }         public long WaitTime { get; set; }         public string LastWaitType { get; set; }         public string Status { get; set; }          public override string ToString()         {             return $"Reads {Reads}, Writes {Writes}, CPU {CpuTime}, RowCount {RowCount}, WaitTime {WaitTime}, LastWaitType {LastWaitType}, Status {Status}";         }     }     public class SqlCommandWithProgress     {           public static async Task ExecuteNonQuery(string ConnectionString, string Query, Action<SessionStats> OnProgress)         {             using (var rdr = await ExecuteReader(ConnectionString, Query, OnProgress))             {                 rdr.Dispose();             }         }          public static async Task<DataTable> ExecuteDataTable(string ConnectionString, string Query, Action<SessionStats> OnProgress)         {             using (var rdr = await ExecuteReader(ConnectionString, Query, OnProgress))             {                 var dt = new DataTable();                  dt.Load(rdr);                 return dt;             }         }           public static async Task<SqlDataReader> ExecuteReader(string ConnectionString, string Query, Action<SessionStats> OnProgress)         {             var mainCon = new SqlConnection(ConnectionString);             using (var monitorCon = new SqlConnection(ConnectionString))             {                 mainCon.Open();                 monitorCon.Open();                    var cmd = new SqlCommand("select @@spid session_id", mainCon);                 var spid = Convert.ToInt32(cmd.ExecuteScalar());                  cmd = new SqlCommand(Query, mainCon);                  var monitorQuery = @" select s.reads, s.writes, r.cpu_time, s.row_count, r.wait_time, r.last_wait_type, r.status from sys.dm_exec_requests r join sys.dm_exec_sessions s    on r.session_id = s.session_id where r.session_id = @session_id";                  var monitorCmd = new SqlCommand(monitorQuery, monitorCon);                 monitorCmd.Parameters.Add(new SqlParameter("@session_id", spid));                  var queryTask = cmd.ExecuteReaderAsync( CommandBehavior.CloseConnection );                  var cols = new { reads = 0, writes = 1, cpu_time =2,row_count = 3, wait_time = 4, last_wait_type = 5, status = 6 };                 while (!queryTask.IsCompleted)                 {                     var firstTask = await Task.WhenAny(queryTask, Task.Delay(1000));                     if (firstTask == queryTask)                     {                         break;                     }                     using (var rdr = await monitorCmd.ExecuteReaderAsync())                     {                         await rdr.ReadAsync();                         var result = new SessionStats()                         {                             Reads = Convert.ToInt64(rdr[cols.reads]),                             Writes = Convert.ToInt64(rdr[cols.writes]),                             RowCount = Convert.ToInt64(rdr[cols.row_count]),                             CpuTime = Convert.ToInt64(rdr[cols.cpu_time]),                             WaitTime = Convert.ToInt64(rdr[cols.wait_time]),                             LastWaitType = Convert.ToString(rdr[cols.last_wait_type]),                             Status = Convert.ToString(rdr[cols.status]),                         };                         OnProgress(result);                      }                  }                 return queryTask.Result;               }         }     } } 

Which you would call something like this:

    class Program     {          static void Main(string[] args)         {             Run().Wait();          }         static async Task Run()         {             var constr = "server=localhost;database=tempdb;integrated security=true";             var sql = @" set nocount on; select newid() d into #foo from sys.objects, sys.objects o2, sys.columns  order by newid(); select count(*) from #foo; ";              using (var rdr = await SqlCommandWithProgress.ExecuteReader(constr, sql, s => Console.WriteLine(s)))             {                 if (!rdr.IsClosed)                 {                     while (rdr.Read())                     {                         Console.WriteLine("Row read");                     }                 }             }             Console.WriteLine("Hit any key to exit.");             Console.ReadKey();           }     } 

Which outputs:

Reads 0, Writes 0, CPU 1061, RowCount 0, WaitTime 0, LastWaitType SOS_SCHEDULER_YIELD, Status running Reads 0, Writes 0, CPU 2096, RowCount 0, WaitTime 0, LastWaitType SOS_SCHEDULER_YIELD, Status running Reads 0, Writes 0, CPU 4553, RowCount 11043136, WaitTime 198, LastWaitType CXPACKET, Status suspended Row read Hit any key to exit. 

Answers 4

That is an interesting question. I have had to implement similar things in the past. In our case the priority was to:

  • Keep client side responsive in case the user doesn't want to stick around and wait.
  • Update the user of action and progress.

What I would do is use threading to run the process in the background like:

HostingEnvironment.QueueBackgroundWorkItem(ct => FunctionThatCallsSQLandTakesTime(p, q, s)); 

Then using a way to estimate work time I would increment a progress bar from client side on a clock. For this, query your data for a variable that gives you a linear relationship to the work time needed by FunctionThatCallsSQLandTakesTime.

For example; the number of active users this month drives the time FunctionThatCallsSQLandTakesTime takes. For each 10000 user it takes 5 minutes. So you can update your progress bar accordingly.

Answers 5

I'm wondering if this might be a reasonable approach:

    IAsyncResult result = cmd2.BeginExecuteNonQuery();     int count = 0;     while (!result.IsCompleted)     {          count++;          if (count % 500 == 0)          {             lblProcessing.Text = "Transactions " + i.ToString();             lblProcessing.Refresh();          }          // Wait for 1/10 second, so the counter          // does not consume all available resources           // on the main thread.          System.Threading.Thread.Sleep(100);     } 
Read More

Friday, August 4, 2017

If passing a file writable stream to the Console constructor in Node.js, is writing to it asynchronous?

Leave a Comment

I've read the docs about the Console object and A note on process I/O, but can't figure out if the following would result in a synchronous or asynchronous operations:

const out = fs.createWriteStream('./out.log') const logger = new Console(out)  logger.log('foo') 

I'm curious about how this acts, especially on a *Nix system. But I wouldn't expect this to act differently on a Windows. The reason I am asking is because I had built a logger which leveraged the Console object, but I don't want the logger to be blocking when writing logs to files while in production.

2 Answers

Answers 1

tldr;
According to Node's official documentation, what you are doing here is synchronous because you are using files.


Writes may be synchronous depending on the what the stream is connected to and whether the system is Windows or Unix:

  • Files: synchronous on Windows and Linux
  • TTYs (Terminals): asynchronous on Windows, synchronous on Unix
  • Pipes (and sockets): synchronous on Windows, asynchronous on Unix

Warning: I strongly recommending not to use these synchronous actions on production services, because synchronous writes block the event loop until the write has completed. This can be a serious drawback when doing production logging.

Reference: Node.js Official Documentations / A note on process I/O

Answers 2

It will be asynchronous.

Internally Console class maintains a callback _stdoutErrorHandler to trigger after the write operation is completed and check for errors. We can test for asynchronicity using it.

const fs = require('fs'); const { Console } = require('console'); const str = new Array(100).fill('').map(() => 'o'.repeat(1000 * 1000)).join(''); const out = fs.createWriteStream('./o.txt'); const logger = new Console(out); logger._stdoutErrorHandler = () => { console.log('written');}; logger.log(str); console.log('hey'); 

You'll see that 'hey' get printed before 'written'.

The note on process I/O applies to process.stdin and process.stdout which are special streams. When they point to files, as in the following:

$ node someCode.js > file.txt 

... in Unix the write operation in Unix will be synchronous. This is handled in lines here. In such cases, process.stdout stream will be connected to a file and not the usual unix file descriptor fd1.

Read More

Monday, July 3, 2017

javascript es5 async plugin architecture

Leave a Comment

I'm trying to figure out a way to structure a new framework for work capable of injecting plugins. The idea is to have each file be loaded asynchronously.

Here is how I would love to configure my plugins:

<script id="target_root" src="assets/js/target/target.js" async="true"></script> <script>     var target = target || {};     target.cmd = target.cmd || [];      target.cmd.push(function () {         target.loadPlugins([             {"name": "root", "src": "assets/js/target/target.root.js"},             {"name": "krux", "src": "assets/js/target/target.krux.js"}         ]).then(             target.init([                 {                     'plugin': 'root',                     'opts': {                         'foo': 'bar'                     }                 },                 {                     'plugin': 'krux',                     'opts': {                         'foo': 'bar'                     }                 }             ])         )     }); </script> 

As I'd be using inline functions (within the DOM) I thought of using a command queue which on load would invoke all pushed functions (a bit like the googletag cmd of DFP).

As stated before each plugin would be loaded asynchronously so the initialization of each of them should only start when all of them are loaded (hence the then() function).

Here you have my script:

var target = (function(root, w, d, c) {     var queueIndex = 0,         amountPluginsLoaded = 0,         pluginsLoaded = [];      root.cmd = {         'queue': root && root.cmd ? root.cmd : [],         'push': function(fn) {             this.queue.push(fn);             this.next();         },         'next': function() {             if (this.queue.length > 0) {                 this.queue.shift()();             }         }     };      root.init = function(plugins) {      };      root.loadPlugins = function(plugins) {         var i = 0,             len = plugins.length;         for(; i < len; i++) {             _loadExternalJS(plugins[i]);         }     };      function _loadExternalJS(plugin) {         var scriptRoot = d.getElementById('target_root'),             scriptElement = d.createElement('script');          scriptElement.setAttribute('type', 'text/javascript');         scriptElement.setAttribute('async', 'true');         scriptElement.onload = function() {             amountPluginsLoaded++;             pluginsLoaded.push(plugin.name);         };         scriptElement.setAttribute('src', plugin.src);         scriptRoot.parentNode.insertBefore(scriptElement, scriptRoot.nextSibling);     }      function _initPlugin(plugin) {      }      for (; queueIndex < root.cmd.queue.length; queueIndex++) {         root.cmd.next();     } }(target || {}, window, document, console)); 

Here you have the basic cmd functionality which would be overridden and the loading of each of the scripts.

What I can't seem to figure is how to fire up the then(). I suppose you'd keep track of it in the _loadExternalJS() in it's onload event (as you can see in the code). But Simply adding an if(amountPluginsLoaded === pluginsLoaded.length) { fire all inits } seems unproductive and not something that belongs in the function. this is why I'd love to implement some then() feature.

Any ideas/opinions?

1 Answers

Answers 1

You could use promise and promise.all to check all of them are loaded.

root.loadPlugins = function(plugins) {     var promiseArray = plugins.map(function(plugin){          return _loadExternalJS(plugin);     });     return Promise.all(promiseArray); };  function _loadExternalJS(plugin) {     return new Promise((resolve, reject) => {        var scriptRoot = d.getElementById('target_root'),            scriptElement = d.createElement('script');         scriptElement.setAttribute('type', 'text/javascript');        scriptElement.setAttribute('async', 'true');        scriptElement.onload = function() {           amountPluginsLoaded++;           pluginsLoaded.push(plugin.name);           resolve(plugin.name);        };        scriptElement.setAttribute('src', plugin.src);        scriptRoot.parentNode.insertBefore(scriptElement, scriptRoot.nextSibling);    }); } 

then

root.loadPlugins().then(function(){     //initialize plugins }); 
Read More

Tuesday, June 27, 2017

Wich is the most efficient way to iterate a directory?

Leave a Comment

Say I have a directory foo, with some number of subdirectories. Each of these subdirectories has between 0 and 5 files of variable length which I would like to process. My initial code looks like so:

    pool.query(`       SET SEARCH_PATH TO public,os_local;     `).then(() => fs.readdirSync(srcpath)         .filter(file => fs.lstatSync(path.join(srcpath, file)).isDirectory())         .map(dir => {           fs.access(`${srcpath + dir}/${dir}_Building.shp`, fs.constants.R_OK, (err) => {             if (!err) {               openShapeFile(`${srcpath + dir}/${dir}_Building.shp`).then((source) => source.read() .then(function dbWrite (result) {               if (result.done) {                 console.log(`done ${dir}`)               } else {     const query = `INSERT INTO os_local.buildings(geometry,                   id,                   featcode,                   version)                   VALUES(os_local.ST_GeomFromGeoJSON($1),                   $2,                   $3,                   $4) ON CONFLICT (id) DO UPDATE SET                     featcode=$3,                     geometry=os_local.ST_GeomFromGeoJSON($1),                     version=$4;`                 return pool.connect().then(client => {                   client.query(query, [geoJson.split('"[[').join('[[').split(']]"').join(']]'),                     result.value.properties.ID,                     result.value.properties.FEATCODE,                     version                   ]).then((result) => {                     return source.read().then(dbWrite)                   }).catch((err) => {                     console.log(err,                       query,                       geoJson.split('"[[').join('[[').split(']]"').join(']]'),                       result.value.properties.ID,                       result.value.properties.FEATCODE,                       version                     )                     return source.read().then(dbWrite)                   })                   client.release()                 })               }             })).catch(err => console.log('No Buildings', err))             }           })            fs.access(`${srcpath + dir}/${dir}__ImportantBuilding.shp`, fs.constants.R_OK, (err) => {             //read file one line at a time             //spin up connection in pg.pool, insert data           })            fs.access(`${srcpath + dir}/${dir}_Road.shp`, fs.constants.R_OK, (err) => {             //read file one line at a time             //spin up connection in pg.pool, insert data           })            fs.access(`${srcpath + dir}/${dir}_Glasshouse.shp`, fs.constants.R_OK, (err) => {             //read file one line at a time             //spin up connection in pg.pool, insert data           })            fs.access(`${srcpath + dir}/${dir}_RailwayStation.shp`, fs.constants.R_OK, (err) => {             //read file one line at a time             //spin up connection in pg.pool, insert data           })         }) 

This mostly works, but it ends up having to wait for the longest file to be fully processed in every subdirectory, resulting in practice in there always being only 1 connection to the database.

Is there a way I could rearchitect this to make better use of my computational resources, while limiting the number of active postgres connections and forcing code to wait until connections become available? (I set them to 20 in the pg poolConfig for node-postgres)

2 Answers

Answers 1

If you need to have your files processed in turn for a certain amount of time, then you can use Streams, timers(for scheduling) and process.nextTick(). There is great manual for understanding streams in nodejs.

Answers 2

Here is an example of getting directory contents using generators. You can start getting the first couple files right away and then use asynchronous code afterward to process files in parallel.

// Dependencies const fs = require('fs'); const path = require('path');  // The generator function (note the asterisk) function* getFilesInDirectory(fullPath, recursive = false) {     // Convert file names to full paths     let contents = fs.readdirSync(fullPath).map(file => {         return path.join(fullPath, file);     });      for(let i = 0; i < contents.length; i++) {         const childPath = contents[i];         let stats = fs.statSync(childPath);         if (stats.isFile()) {             yield childPath;         } else if (stats.isDirectory() && recursive) {             yield* getFilesInDirectory(childPath, true);         }     } } 

Usage:

function handleResults(results) {     ... // Returns a promise }  function processFile(file) {     ... // Returns a promise }  var files = getFilesInDirectory(__dirname, true); var result = files.next(); var promises = []; while(!result.done) {     console.log(result.value);     file = files.next();     // Process files in parallel     var promise = processFile(file).then(handleResults);     promises.push(promise); }  promise.all(promises).then() {     console.log(done); } 
Read More

Tuesday, April 25, 2017

COM asynchronous call doesn't respect the message filter

Leave a Comment

I have an STA COM object that implements a custom interface. My custom interface has a custom proxy stub that was built from the code generated by the MIDL-compiler. I would like to be able to asynchronously make calls to the interface from other apartments. I'm finding that the synchronous interface calls respect the OLE message filter on the calling thread, but the asynchronous interface calls do not. This means that COM asynchronous calls cannot be used in a fire-and-forget manner if the calling apartment has a message filter that suggests retrying the call later.

Is this expected? Is there any way around this other than not using a message filter, not using fire-and-forget operations, or having a separate homegrown component just to manage fire-and-forget operations?

For the code below, MessageFilter is a simple, in-module implementation of IMessageFilter that routes calls to lambdas. If I do not use message filters, both the synchronous and asynchronous calls work fine. If I use the message filters shown below, the synchronous call works (after the main STA message filter stops returning SERVERCALL_RETRYLATER) but the asynchronous call immediately fails and never retries.

The main STA has a message filter that defers for some period of time.

// establish deferral time chrono::time_point<chrono::system_clock> defer_until = ...;  // create message filter auto message_filter = new MessageFilter; message_filter->AddRef(); message_filter->handle_incoming_call     = [defer_until](DWORD, HTASK, DWORD, LPINTERFACEINFO)       {           return chrono::high_resolution_clock::now() >= defer_until               ? SERVERCALL_ISHANDLED               : SERVERCALL_RETRYLATER;       };  // register message filter CoRegisterMessageFilter(message_filter, nullptr); 

Another STA sets up its own message filter to tell COM to retry.

// create message filter auto message_filter = new MessageFilter; message_filter->AddRef(); message_filter->retry_rejected_call     = [](HTASK, DWORD, DWORD)       {           return 0; // retry immediately       };  // register message filter CoRegisterMessageFilter(message_filter, nullptr); 

In that secondary STA, I get a proxy for the object interface from the main STA.

// get global interface table IGlobalInterfaceTablePtr global_interface_table; global_interface_table.CreateInstance(CLSID_StdGlobalInterfaceTable);  // get interface reference IMyInterfacePtr object_interface; global_interface_table->GetInterfaceFromGlobal(cookie, __uuidof(IMyInterface), reinterpret_cast<LPVOID*>(&object_interface))); 

This works:

// execute synchronously HRESULT hr = object_interface->SomeMethod();  /* final result, after the deferral period: hr == S_OK */ 

This does not work:

// get call factory ICallFactoryPtr call_factory; object_interface->QueryInterface(&call_factory);  // create async call AsyncIMyInterfacePtr async_call; call_factory->CreateCall(__uuidof(AsyncIMyInterface), nullptr, __uuidof(AsyncIMyInterface), reinterpret_cast<LPUNKNOWN*>(&async_call)));  // begin executing asynchronously async_call->Begin_SomeMethod();  // end executing asynchronously HRESULT hr = async_call->Finish_SomeMethod();  /* final result, immediate: hr == RPC_E_SERVERCALL_RETRYLATER */ 

0 Answers

Read More

Tuesday, April 11, 2017

How does asynchronous training work in distributed Tensorflow?

Leave a Comment

I've read Distributed Tensorflow Doc, and it mentions that in asynchronous training,

each replica of the graph has an independent training loop that executes without coordination.

From what I understand, if we use parameter-server with data parallelism architecture, it means each worker computes gradients and updates its own weights without caring about other workers updates for distributed training Neural Network. As all weights are shared on parameter server (ps), I think ps still has to coordinate (or aggregate) weight updates from all workers in some way. I wonder how does the aggregation work in asynchronous training. Or in more general words, how does asynchronous training work in distributed Tensorflow?

3 Answers

Answers 1

Looking at the example in the documentation you link to:

with tf.device("/job:ps/task:0"):   weights_1 = tf.Variable(...)   biases_1 = tf.Variable(...)  with tf.device("/job:ps/task:1"):   weights_2 = tf.Variable(...)   biases_2 = tf.Variable(...)  with tf.device("/job:worker/task:7"):   input, labels = ...   layer_1 = tf.nn.relu(tf.matmul(input, weights_1) + biases_1)   logits = tf.nn.relu(tf.matmul(layer_1, weights_2) + biases_2)   # ...   train_op = ...  with tf.Session("grpc://worker7.example.com:2222") as sess:   for _ in range(10000):     sess.run(train_op) 

You can see that the training is distributed on three machines which all share a copy of identical weights, but as is mentioned just below the example:

In the above example, the variables are created on two tasks in the ps job, and the compute-intensive part of the model is created in the worker job. TensorFlow will insert the appropriate data transfers between the jobs (from ps to worker for the forward pass, and from worker to ps for applying gradients).

In other words, one gpu is used to calculate the forward pass and then transmits the results to the other two machines, while each of the other machines calculate the back propagation for a part of the weights and then send the results to the other machines so they can all update their weights appropriately.

GPUs are used to speed up matrix multiplications and parallel mathematical operations which are very intensive for both forward pass and back propagation. So distributed training simply means that you distribute these operations on many GPUs, the model is still synced between the machines, but now the back propagation of different weights can be calculated in parallel and the forward pass on a different mini-batch can be calculated at the same time as backprop from the previous mini-batch is still being calculated. Distributed training does not mean that you have totally independent models and weights on each machine.

Answers 2

In asynchronous training there is no synchronization of weights among the workers. The weights are stored on the parameter server. Each worker loads and changes the shared weights independently from each other. This way if one worker finished an iteration faster than the other workers, it proceeds with the next iteration without waiting. The workers only interact with the shared parameter server and don't interact with each other.

Overall it can (depending on the task) speedup the computation significantly. However the results are sometimes worse than the ones obtained with the slower synchronous updates.

Answers 3

When you train asynchronously in Distributed TensorFlow, a particular worker does the following:

  1. The worker reads all of the shared model parameters in parallel from the PS task(s), and copies them to the worker task. These reads are uncoordinated with any concurrent writes, and no locks are acquired: in particular the worker may see partial updates from one or more other workers (e.g. a subset of the updates from another worker may have been applied, or a subset of the elements in a variable may have been updated).

  2. The worker computes gradients locally, based on a batch of input data and the parameter values that it read in step 1.

  3. The worker sends the gradients for each variable to the appropriate PS task, and applies the gradients to their respective variable, using an update rule that is determined by the optimization algorithm (e.g. SGD, SGD with Momentum, Adagrad, Adam, etc.). The update rules typically use (approximately) commutative operations, so they may be applied independently on the updates from each worker, and the state of each variable will be a running aggregate of the sequence of updates received.

In asynchronous training, each update from the worker is applied concurrently, and the updates may be somewhat coordinated if the optional use_locking=True flag was set when the respective optimizer (e.g. tf.train.GradientDescentOptimizer) was initialized. Note however that the locking here only provides mutual exclusion for two concurrent updates, and (as noted above) reads do not acquire locks; the locking does not provide atomicity across the entire set of updates.

(By contrast, in synchronous training, a utility like tf.train.SyncReplicasOptimizer will ensure that all of the workers read the same, up-to-date values for each model parameter; and that all of the updates for a synchronous step are aggregated before they are applied to the underlying variables. To do this, the workers are synchronized by a barrier, which they enter after sending their gradient update, and leave after the aggregated update has been applied to all variables.)

Read More

Sunday, April 9, 2017

Angular 2 fakeAsync waiting for timeout in a function using tick()?

Leave a Comment

I'm trying to get the results from a mock backend in Angular 2 for unit testing. Currently, we are using fakeAsync with a timeout to simulate the passing of time.

current working unit test

it('timeout (fakeAsync/tick)', fakeAsync(() => {     counter.getTimeout();     tick(3000); //manually specify the waiting time })); 

But, this means that we are limited to a manually defined timeout. Not when the async task is completed. What I'm trying to do is getting tick() to wait until the task is completed before continuing with the test.

This does not seem to work as intended.

Reading up on the fakeAsync and tick the answer here explains that:

tick() simulates the asynchronous passage of time.

I set up a plnkr example simulating this scenario.

Here, we call the getTimeout() method which calls an internal async task that has a timeout. In the test, we try wrapping it and calling tick() after calling the getTimeout() method.

counter.ts

getTimeout() {   setTimeout(() => {     console.log('timeout')   },3000) } 

counter.specs.ts

it('timeout (fakeAsync/tick)', fakeAsync(() => {     counter.getTimeout();     tick(); })); 

But, the unit test fails with the error "Error: 1 timer(s) still in the queue."

Does the issue here in the angular repo have anything to do with this?

Is it possible to use tick() this way to wait for a timeout function? Or is there another approach that I can use?

2 Answers

Answers 1

I normally use the flushMicrotasks method in my unit tests for use with my services. I had read that tick() is very similar to flushMicrotasks but also calls the jasmine tick() method.

Answers 2

Try this bro:

// I had to do this: it('timeout (fakeAsync/tick)', (done) => {   fixture.whenStable().then(() => {        counter.getTimeout();        tick();     done();   }); }); 

Source

Read More

latch(used for awaiting async response) freezes the WebView (and the UI)

Leave a Comment

I have an app that displays a webview on the whole layout. Sometimes I need to call an async method, that async operation is done by a 3-party sdk, and then I wait for it for a while until I get the response to a designated listener. I have solved it with a latch - once the response is received in the listener, I countDown the latch and then the initiating method can continue with this response. Unfortunately, when I do this, the WebView is stuck. I imagined the native UI would be stuck , but I didn't expect the webview to get frozen as well. How can that be overcome?

To make it clearer, here is an example. I need the ajaxFunc to wait until MyAsyncListener gets a certain response, and then return this exact response.

part of JS I inject to the webview :

var response = jsHandler.ajaxFunc(request.data); 

I have a variable global variable called response.

public class JavaScriptInterface {      @JavascriptInterface      public String ajaxFunc(String data)      {          return MyUtils.handleData( data );      } } 

the handleData method :

 public String handleData( String data )  {      SomeClass.startAsyncRequest(); // starts the async request, response is to come at the listener's callbacks .       latch = new CountDownLatch(1);      try {          latch.await(30, TimeUnit.SECONDS);      }      catch (InterruptedException e) {          e.printStackTrace();      }       return response;    } 

now, once the handleData function calls a function, that does something asynchronously, the async function then returns some answer inside some Listener :

myAsyncListener = new MyAsyncListener() {     @Override         public Response handleEvent(CustomEvent event) {             //Now I need to return this 'event' back to the handData/ajaxFunc function <--               response = event.getName();             latch.countDown();          }     }); 

3 Answers

Answers 1

I need the ajaxFunc to wait until MyAsyncListener gets a certain response, and then return this exact response.

Since you are dispatching an async request, you shouldn't expect the response to arrive in the same method call you made to start the async code. If you do this, the caller thread will block until the async response arrives, that is, it won't be async at all.

You can redesign your code to something like this:

public class JavaScriptInterface {     @JavascriptInterface     public void ajaxFunc(String data) {         // draw a waiting animation or something         MyUtils.handleData(data);     } } 
public void handleData(String data) {     SomeClass.startAsyncRequest(); } 
myAsyncListener = new MyAsyncListener() {     @Override     public void handleEvent(CustomEvent event) {         // Do what you need to do         // (update UI, call javascript etc.).         //         // Mind the thread that will execute this callback         // to prevent multithreading issues.     } } 

Answers 2

You have put CountDownLatch inside your code which will cause blocking of your main thread. Thats the reason of lag on UI.

For better you should show some ProgressDialog before doing main work of Async task which generally written in doInBackground() method of Async task and hide it after completing your task, Async provide onPostExecute() method for that purpose.

If you need to put some timeout like your CountDownLatch is doing, you can write timer in doInBackground() of Async. That timer will stop your current Async will allotted time is elapsed.

Update, you could use EventBus for your purpose -

EventBus works on Publish/Subscribe pattern. You can subscribe in Activity and publish result from JavaScriptInterface.

Add it in gradle using -

compile 'org.greenrobot:eventbus:3.0.0' 

In your Activity start subscribing, generally subscriptions done in onCreate method of Activity -

EventBus.getDefault().register(this); 

Also remove subscriptions in onDestroy method of Activity or if your work is done.

EventBus.getDefault().unregister(this); 

To listen subscription use below code in your Activity -

@Subscribe(threadMode = ThreadMode.MAIN)        public void onMessageEvent(MyMessageEvent event) {      // Do your work after getting result from ajaxFunc method  }; 

You just have to post message notification from your method now and remove CountDown latch from your code if it is not needed somewhere else.

myAsyncListener = new MyAsyncListener() {     @Override         public Response handleEvent(CustomEvent event){          response = event.getName();         // Create object of message and post it         final MyMessageEvent msgEvent = new MessageEvent(response);         EventBus.getDefault().post(msgEvent);     } }); 

MyMessageEvent.class

import android.support.annotation.NonNull;  public class MyMessageEvent {      private String mMessage;      public MyMessageEvent(@NonNull final String message) {         mMessage = message;     }      public String getMessage() {         return mMessage;     }  } 

Answers 3

Android Thread Model

As JCIP introduced, many UI framework is single threaded. They use thread confinement to avoid deadlock and integrity of data. Android also use this thread model.

By default, all components of the same application run in the same process and thread (called the “main” thread).

So if you wait on main thread by using lacth, the UI will be not updated or response your action.

Background Task

But sometimes, we want to perform some long time task like using network to download something and read from db. In order to make UI responsive, we should perform those jobs in another thread (Notice: not in the Service, which default still run on the main thread).

Java Way

So you may use thread or executorto fetch your data, then read data back into main thread like following method when some event happens:

Activity.runOnUiThread(Runnable) 

Android Way

Or you may use Android native AsyncTask which is conveinent. For example, when you want to check the username/password of user, you have to connect to your server to verify it. In such scenario, you can put the request and verification process into a AsyncTask and the UI thread can make some animation when there is no response. Following is some code:

public class UserLoginTask extends AsyncTask<Void, Void, Boolean> {      private final String mName;     private final String mPassword;      UserLoginTask(String name, String password) {         mName = name;         mPassword = password;     }      // backgroud thread     @Override     protected Boolean doInBackground(Void... params) {         // network access.          for (String credential : CREDENTIALS) {             String[] pieces = credential.split(":");             if (pieces[0].equals(mName)) {                 // Account exists, return true if the password matches.                 return pieces[1].equals(mPassword);             }         }          // register the new account here.         return true;     }      // UI thread     @Override     protected void onPostExecute(final Boolean success) {         mAuthTask = null;         showProgress(false);          if (success) {             // start next             finish();             Intent intent = new Intent(LoginActivity.this, Drawer.class);             startActivity(intent);         } else {             mPasswordView.setError(getString( R.string.error_incorrect_password ));             mPasswordView.requestFocus();         }     }      @Override     protected void onCancelled() {         mAuthTask = null;         showProgress(false);     } } 

Ref:

Read More

Wednesday, January 25, 2017

ASP.NET MVC with Async Action

Leave a Comment

I need to send an asynchronous email from an Async action. I do not understand why the following error is happening, being that I use this same class in other projects and use the same form only without errors, everything quiet.

Error:

The asynchronous action method 'EsqueciMinhaSenhaAsync' returns a Task, which cannot be executed synchronously.

Action:

        [AllowAnonymous]         [HttpPost, ValidateAntiForgeryToken]         public async Task<ActionResult> EsqueciMinhaSenhaAsync(UsuarioEsqueciMinhaSenhaViewModel vModel)         {             if (ModelState.IsValid)             {                 var conteudo = "este é o conteudo do email";                 var nomeRemetente = "esse é o nome do remetente";                  if(await EmailService.SendAsync(Language.PasswordRecovery, conteudo, vModel.EmailOuUsername, nomeRemetente))                 {                     TempData["MensagemRetorno"] = Language.EmailSendedWithSuccess;                     return View("login");                 }             }              TempData["MensagemRetorno"] = Language.ErrorSendingEmail;             return View("EsqueciMinhaSenha");         } 

My Email Service:

    public static async Task<bool> SendAsync(string assunto, string conteudo, string destinatario, string nomeDestinatario)     {         // Habilitar o envio de e-mail         var appSetting = ConfigurationManager.AppSettings;          if (appSetting != null && appSetting.Count >= 7 && !string.IsNullOrEmpty(assunto) && !string.IsNullOrEmpty(conteudo) && !string.IsNullOrEmpty(destinatario) && !string.IsNullOrEmpty(nomeDestinatario))         {             int port = 0;             bool useSSl = false;              using (var msg = new MailMessage             {                 From = new MailAddress(appSetting["EmailFrom"], appSetting["EmailNameFrom"]),                 Body = WebUtility.HtmlEncode(conteudo)             })             {                 int.TryParse(appSetting["EmailPort"], out port);                 bool.TryParse(appSetting["EmailUseSSL"], out useSSl);                   msg.ReplyToList.Add(destinatario);                 msg.To.Add(new MailAddress(destinatario, nomeDestinatario));                 msg.Subject = assunto;                 msg.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(msg.Body, null, MediaTypeNames.Text.Plain));                 msg.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(msg.Body, null, MediaTypeNames.Text.Html));                  using (var smtpClient = new SmtpClient(appSetting["EmailServer"], port))                 {                     var credentials = new NetworkCredential(appSetting["EmailUserName"], appSetting["EmailPassword"]);                     smtpClient.Credentials = credentials;                     smtpClient.EnableSsl = useSSl;                     await smtpClient.SendMailAsync(msg);                      return await Task.FromResult(true);                 }             }         }          return await Task.FromResult(false);     } 

2 Answers

Answers 1

I was having same sort of issue, and when I made all possible path awaitable then issue resolved.

Please make changes to your action EsqueciMinhaSenhaAsync

currently your last line is:

return View("EsqueciMinhaSenha");

change it to

//It looks async/wait pattern expects all paths to have awaitable if async is used

return await View("EsqueciMinhaSenha");

Answers 2

1) Why don't you add sync API version based on SmtpClient.SendMail? https://msdn.microsoft.com/en-us/library/swas0fwc(v=vs.110).aspx

public static bool SendSync(string assunto, string conteudo, string destinatario, string nomeDestinatario) {     // Habilitar o envio de e-mail     var appSetting = ConfigurationManager.AppSettings;      if (appSetting != null && appSetting.Count >= 7 && !string.IsNullOrEmpty(assunto) && !string.IsNullOrEmpty(conteudo) && !string.IsNullOrEmpty(destinatario) && !string.IsNullOrEmpty(nomeDestinatario))     {         int port = 0;         bool useSSl = false;          using (var msg = new MailMessage         {             From = new MailAddress(appSetting["EmailFrom"], appSetting["EmailNameFrom"]),             Body = WebUtility.HtmlEncode(conteudo)         })         {             int.TryParse(appSetting["EmailPort"], out port);             bool.TryParse(appSetting["EmailUseSSL"], out useSSl);               msg.ReplyToList.Add(destinatario);             msg.To.Add(new MailAddress(destinatario, nomeDestinatario));             msg.Subject = assunto;             msg.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(msg.Body, null, MediaTypeNames.Text.Plain));             msg.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(msg.Body, null, MediaTypeNames.Text.Html));              using (var smtpClient = new SmtpClient(appSetting["EmailServer"], port))             {                 var credentials = new NetworkCredential(appSetting["EmailUserName"], appSetting["EmailPassword"]);                 smtpClient.Credentials = credentials;                 smtpClient.EnableSsl = useSSl;                 smtpClient.SendMail(msg);                  return true;             }         }     }      return false; } 

2) Another option is to use IAsyncOperation as a returning result of your email service. That way, you can use this as both async way (via await) and sync way like that:

var asyncOp = EmailService.SendAsync(some-params-here); var task = asyncOp.AsTask(); task.Wait(); return task.Result; // TODO it's nice to care about exceptions too! 
Read More

Monday, January 9, 2017

NodeJS 7: How to Show the Correct Stack Trace in Async Functions

Leave a Comment

When I have an error in an async function, like in async or bluebird. I don't have the correct line number, which makes it hard for me to find the error.

unknownFunction("A")#show me the correct line number in the trace async.timesSeries 100,   (index, next) ->      unknownFunction("B") #show me only the line number where I catch the error  process.on 'uncaughtException', (err)->   console.log err.stack   console.trace err    throw err 

Question: How can I get the correct line number instead of the line number where the error is catched?

PS: I found and tried this so far: https://github.com/groundwater/node-stackup But it gives me a lot of unrelated line numbers.

EDIT:

This is how I init mongoose with bluebird:

Promise = require("bluebird") Promise.config({   longStackTraces: true   warnings: {     wForgottenReturn: false   } }) mongoose = require('mongoose') mongoose.Promise = Promise mongoose.set('error', true) 

Example correct:

enter image description here

  ReferenceError: unknownFunction is not defined    - patient.update.js:267  

Example incorrect:

enter image description here

somepath/.tmp/serve/server.js:294       throw err;       ^  ReferenceError: unknownFunction2 is not defined 

The error is in patient.update.js line nr 268

Longjohn

With longjohn

somepath/node_modules/longjohn/dist/longjohn.js:192         throw e;         ^  ReferenceError: unknownFunction2 is not defined 

Stack up

This is what I mean with node-stack-up unrelated lines (same test with unknownFunction2):

    /somepath/myApp/.tmp/serve/server.js:296       throw err;       ^  ReferenceError: unknownFunction2 is not defined      ---- async ----    - glue.js:150 asyncWrap     [myApp]/[async-listener]/glue.js:150:28    - glue.js:401 wrapCallback     [myApp]/[async-listener]/glue.js:401:35    - index.js:16 process.nextTick     [myApp]/[async-listener]/index.js:16:26    - index.js:126 Kareem.execPost     [myApp]/[kareem]/index.js:126:20    - index.js:251      [myApp]/[kareem]/index.js:251:15    - query.js:1616      [myApp]/[mongoose]/lib/query.js:1616:5    - document.js:317 model.Document.init     [myApp]/[mongoose]/lib/document.js:317:5    - query.js:1609 completeOne     [myApp]/[mongoose]/lib/query.js:1609:10    - query.js:1271 Immediate.<anonymous>     [myApp]/[mongoose]/lib/query.js:1271:13    - utils.js:137 Immediate.<anonymous>     [myApp]/[mquery]/lib/utils.js:137:16    - timers.js:649 runCallback     timers.js:649:20    - timers.js:622 tryOnImmediate     timers.js:622:5    - timers.js:594 processImmediate [as _immediateCallback]     timers.js:594:5       ---- async ----    - glue.js:150 asyncWrap     [myApp]/[async-listener]/glue.js:150:28    - glue.js:401 wrapCallback     [myApp]/[async-listener]/glue.js:401:35    - index.js:16 process.nextTick     [myApp]/[async-listener]/index.js:16:26    - pool.js:454 handleOperationCallback     [myApp]/[mongoose]/[mongodb-core]/lib/connection/pool.js:454:24    - pool.js:490      [myApp]/[mongoose]/[mongodb-core]/lib/connection/pool.js:490:9    - pool.js:429 authenticateStragglers     [myApp]/[mongoose]/[mongodb-core]/lib/connection/pool.js:429:16    - pool.js:463 Connection.messageHandler     [myApp]/[mongoose]/[mongodb-core]/lib/connection/pool.js:463:5    - connection.js:309 Socket.<anonymous>     [myApp]/[mongoose]/[mongodb-core]/lib/connection/connection.js:309:     22    - events.js:96 emitOne     events.js:96:13    - events.js:188 Socket.emit     events.js:188:7    - _stream_readable.js:176 readableAddChunk     _stream_readable.js:176:18    - _stream_readable.js:134 Socket.Readable.push     _stream_readable.js:134:10    - net.js:551 TCP.onread     net.js:551:20    - glue.js:188 TCP.onread     [myApp]/[async-listener]/glue.js:188:31       ---- async ----    - glue.js:150 asyncWrap     [myApp]/[async-listener]/glue.js:150:28    - glue.js:401 wrapCallback     [myApp]/[async-listener]/glue.js:401:35    - index.js:88 Socket.connect     [myApp]/[async-listener]/index.js:88:29    - net.js:74 Object.exports.connect.exports.createConnection     net.js:74:35    - connection.js:389 Connection.connect     [myApp]/[mongoose]/[mongodb-core]/lib/connection/connection.js:389:     11    - pool.js:1059 _createConnection     [myApp]/[mongoose]/[mongodb-core]/lib/connection/pool.js:1059:14    - pool.js:1151      [myApp]/[mongoose]/[mongodb-core]/lib/connection/pool.js:1151:13    - pool.js:1082 waitForAuth     [myApp]/[mongoose]/[mongodb-core]/lib/connection/pool.js:1082:39    - pool.js:1090      [myApp]/[mongoose]/[mongodb-core]/lib/connection/pool.js:1090:5    - pool.js:957      [myApp]/[mongoose]/[mongodb-core]/lib/connection/pool.js:957:21    - glue.js:188      [myApp]/[async-listener]/glue.js:188:31    - next_tick.js:67 _combinedTickCallback     internal/process/next_tick.js:67:7    - next_tick.js:98 process._tickCallback     internal/process/next_tick.js:98:9       ---- async ----    - glue.js:150 asyncWrap     [myApp]/[async-listener]/glue.js:150:28    - glue.js:401 wrapCallback     [myApp]/[async-listener]/glue.js:401:35    - index.js:16 process.nextTick     [myApp]/[async-listener]/index.js:16:26    - pool.js:956 Pool.write     [myApp]/[mongoose]/[mongodb-core]/lib/connection/pool.js:956:13    - cursor.js:288 CommandCursor.Cursor._find     [myApp]/[mongoose]/[mongodb-core]/lib/cursor.js:288:22    - cursor.js:588 nextFunction     [myApp]/[mongoose]/[mongodb-core]/lib/cursor.js:588:10    - cursor.js:696 CommandCursor.Cursor.next [as _next]     [myApp]/[mongoose]/[mongodb-core]/lib/cursor.js:696:3    - cursor.js:849 fetchDocs     [myApp]/[mongoose]/[mongodb]/lib/cursor.js:849:10    - cursor.js:876 toArray     [myApp]/[mongoose]/[mongodb]/lib/cursor.js:876:3    - cursor.js:829 CommandCursor.Cursor.toArray     [myApp]/[mongoose]/[mongodb]/lib/cursor.js:829:44    - db.js:1662 indexInformation     [myApp]/[mongoose]/[mongodb]/lib/db.js:1662:39    - db.js:1626 Db.indexInformation     [myApp]/[mongoose]/[mongodb]/lib/db.js:1626:44    - db.js:1129 ensureIndex     [myApp]/[mongoose]/[mongodb]/lib/db.js:1129:8    - db.js:1105 Db.ensureIndex     [myApp]/[mongoose]/[mongodb]/lib/db.js:1105:44    - collection.js:1891 ensureIndex     [myApp]/[mongoose]/[mongodb]/lib/collection.js:1891:13    - collection.js:1879 Collection.ensureIndex     [myApp]/[mongoose]/[mongodb]/lib/collection.js:1879:44    - collection.js:126 NativeCollection.(anonymous function) [as ensureIndex]     [myApp]/[mongoose]/lib/drivers/node-mongodb-native/collection.js:12     6:28    - model.js:1019 create     [myApp]/[mongoose]/lib/model.js:1019:22    - model.js:1033 Immediate.<anonymous>     [myApp]/[mongoose]/lib/model.js:1033:7    - timers.js:649 runCallback     timers.js:649:20    - timers.js:622 tryOnImmediate     timers.js:622:5    - timers.js:594 processImmediate [as _immediateCallback]     timers.js:594:5       ---- async ----    - glue.js:150 asyncWrap     [myApp]/[async-listener]/glue.js:150:28    - glue.js:401 wrapCallback     [myApp]/[async-listener]/glue.js:401:35    - index.js:16 process.nextTick     [myApp]/[async-listener]/index.js:16:26    - _stream_writable.js:377 onwrite     _stream_writable.js:377:15    - _stream_writable.js:90 WritableState.onwrite     _stream_writable.js:90:5    - net.js:724 Socket._writeGeneric     net.js:724:5    - net.js:734 Socket._write     net.js:734:8    - _stream_writable.js:334 doWrite     _stream_writable.js:334:12    - _stream_writable.js:320 writeOrBuffer     _stream_writable.js:320:5    - _stream_writable.js:247 Socket.Writable.write     _stream_writable.js:247:11    - net.js:661 Socket.write     net.js:661:40    - connection.js:500 Connection.write     [myApp]/[mongoose]/[mongodb-core]/lib/connection/connection.js:500:     53    - pool.js:1137      [myApp]/[mongoose]/[mongodb-core]/lib/connection/pool.js:1137:26    - pool.js:1082 waitForAuth     [myApp]/[mongoose]/[mongodb-core]/lib/connection/pool.js:1082:39    - pool.js:1090      [myApp]/[mongoose]/[mongodb-core]/lib/connection/pool.js:1090:5    - pool.js:957      [myApp]/[mongoose]/[mongodb-core]/lib/connection/pool.js:957:21    - glue.js:188      [myApp]/[async-listener]/glue.js:188:31    - next_tick.js:67 _combinedTickCallback     internal/process/next_tick.js:67:7    - next_tick.js:98 process._tickCallback     internal/process/next_tick.js:98:9       ---- async ----    - glue.js:150 asyncWrap     [myApp]/[async-listener]/glue.js:150:28    - glue.js:401 wrapCallback     [myApp]/[async-listener]/glue.js:401:35    - index.js:16 process.nextTick     [myApp]/[async-listener]/index.js:16:26    - pool.js:956 Pool.write     [myApp]/[mongoose]/[mongodb-core]/lib/connection/pool.js:956:13    - cursor.js:288 Cursor._find     [myApp]/[mongoose]/[mongodb-core]/lib/cursor.js:288:22    - cursor.js:588 nextFunction     [myApp]/[mongoose]/[mongodb-core]/lib/cursor.js:588:10    - cursor.js:696 Cursor.next [as _next]     [myApp]/[mongoose]/[mongodb-core]/lib/cursor.js:696:3    - cursor.js:672 nextObject     [myApp]/[mongoose]/[mongodb]/lib/cursor.js:672:8    - cursor.js:262 Cursor.next     [myApp]/[mongoose]/[mongodb]/lib/cursor.js:262:12    - collection.js:1401 findOne     [myApp]/[mongoose]/[mongodb]/lib/collection.js:1401:10    - collection.js:1387 Collection.findOne     [myApp]/[mongoose]/[mongodb]/lib/collection.js:1387:44    - collection.js:126 NativeCollection.(anonymous function) [as findOne]     [myApp]/[mongoose]/lib/drivers/node-mongodb-native/collection.js:12     6:28    - node.js:38 NodeCollection.findOne     [myApp]/[mquery]/lib/collection/node.js:38:19    - mquery.js:1787 model.Query.Query.findOne     [myApp]/[mquery]/lib/mquery.js:1787:20    - query.js:1260 model.Query.Query._findOne     [myApp]/[mongoose]/lib/query.js:1260:22    - index.js:239      [myApp]/[kareem]/index.js:239:8    - index.js:18      [myApp]/[kareem]/index.js:18:7    - glue.js:188      [myApp]/[async-listener]/glue.js:188:31    - next_tick.js:67 _combinedTickCallback     internal/process/next_tick.js:67:7    - next_tick.js:98 process._tickCallback     internal/process/next_tick.js:98:9       ---- async ----    - glue.js:150 asyncWrap     [myApp]/[async-listener]/glue.js:150:28    - glue.js:401 wrapCallback     [myApp]/[async-listener]/glue.js:401:35    - index.js:16 process.nextTick     [myApp]/[async-listener]/index.js:16:26    - index.js:17 Kareem.execPre 

3 Answers

Answers 1

The node-stackup, longjohn, and Bluebird's long stack traces are the best solutions available. I'm not sure what you mean by "it gives me a lot of unrelated line numbers." It's giving you a stack trace, so unless you've written all the code and have zero dependencies then you're bound to see function calls to lines you didn't write regardless of whether the operation is asynchronous or not.

Essentially what these libraries do is just stitch detached stack traces together. Normally JavaScript stack traces won't include anything involving an asynchronous operation, only the most recent synchronous function calls. These libraries monkey patch most methods that can introduce asynchronous behavior (process.nextTick, setTimeout, EventEmitter, etc.). They add code which creates a new stack trace at each of these call sites and stores all of these until an error occurs. It will join all of the stored stack traces together so you can actually walk back through all of the asynchronous operations until you get to the original call site.

Answers 2

You can try the following tool decofun debug tool to deanomise the anonymous functions.

Complete details mentioned in the following answer written by me in this

thread

The documentation is as mentioned here

Answers 3

For any uncaughtException the server will stop in order to make the server keep on running even when there is an uncaught exception what i have done is created a separate collection for storing error, save error once an uncaught exception occurs and returns.

Collection

var ErrorSchema = new mongoose.Schema({   err_Message:{type:String},   err_Stack:{type:String},   date:{type:Date} }); 

Controller

process.on('uncaughtException', function (err) {     console.log(err);     console.error((new Date).toUTCString() + ' uncaughtException:', err.message);     console.error(err.stack);      var newError = new Error;     newError.err_Message = err.message;     newError.err_Stack = err.stack;     newError.date = moment();     newError.save(function(saveErr,errData){         if(!saveErr)             console.log('New Error is saved');         else             console.log('Error in saving error');     });     //process.exit(1) }); 

The above methods stores the uncaught exception in the Error collection and the process/server does not stops.

Reference: Already answered in Nodejs debug errors in production

Hope this helps.

Read More