HOAB

History of a bug

React and events

Rédigé par gorki Aucun commentaire

Problème :

J'utilise React pour développer une application frontend et j'utilise les méthodes de base Javascsript pour gérer les événements venant du serveur ou en interne Front.

J'ai trouvé sur internet quelques fonctions utiles pour gérer les événements (je n'ai pas retrouvé où !) :

  • on : abonnement
  • off : désabonnement
  • trigger : déclencher un évenement

Pour mon usage, j'ai customisé ces fonctions en ajoutant une callback en paramètre. Résultat j'ai ce code : 

function on(eventType:string, state:any, listener:(detail:MyEvent) => void) {
    const resultFunction = function(event:any) {
        listener(event.detail)
    };
    document.addEventListener(eventType, resultFunction);

Cela me permet de gérer des événements qui héritent de MyEvent.

Le problème est que, ce faisant, je crée une fonction anonyme à chaque souscription et que du coup il est impossible d'utiliser removeEventListener lorsque le composant se démonte.

Solution :

Indirectement c'est ce guide qui m'a aidé : https://dev.to/marcostreng/how-to-really-remove-eventlisteners-in-react-3och

L'idée était donc bien de garder la référence à la fonction anonyme créée (qui me permet de gérer des callbacks génériques), mais comment simplifier l'usage pour éviter de devoir faire stocker la référence à cette fonction anonyme par tous les composants ?

Eh bien en la stockant moi-même directement dans le state !

Sur le désabonnement, je vais chercher dans le state, la référence à la fonction anonyme stockée pour mon type d'événement.


function buildKey(eventType: string) {
    return 'clientside-events.listener.' + eventType;
}

function on(eventType:string, state:any, listener:(detail:MyEvent) => void) {
    const resultFunction = function(event:any) {
        listener(event.detail)
    };
    document.addEventListener(eventType, resultFunction);
    if (state !== null) {
        if (!state.listeners) {
            state.listeners = new Map();
        }
        state.listeners.set(buildKey(eventType), resultFunction);
    }
    return resultFunction;
}

function off(eventType:string, state:any) {
    if (state !== null && state.listeners) {
        document.removeEventListener(eventType, state.listeners.get(buildKey(eventType)));
    } else {
        console.warn('Trying to remove a listener but not found for ' + eventType)
    }
}

function trigger(eventType:string, message:ShaanEvent) {
    const event = new CustomEvent(eventType, { detail: message });
    document.dispatchEvent(event);
}

export { on, off, trigger };

 

Cannot create GC thread but a lot of memory

Rédigé par gorki Aucun commentaire

Problem :

Launching a JVM I have the message : "Cannot create GC thread. Out of system resources"

  • Enough memory
  • Enough swap
  • Enough ulimit
  • Enough threads-max
  • Enough CPU

Event extend the PID limit...

Important (at the end) : debian version = 10.11

Solution :

After a hours of googling, I found :

But none of these solutions works and none was matching the number I had :

  • number of open files < ulimit -n
  • maximum process/tasks < ulimit -u

But in a thread, I found something that was working : UserTasksMax.
I'm running SystemD, I have around 10805 task running for my user.
And from : https://manpages.debian.org/stretch/systemd/logind.conf.5.en.html

UserTasksMax=

Sets the maximum number of OS tasks each user may run concurrently. This controls the TasksMax= setting of the per-user slice unit, see systemd.resource-control(5) for details. If assigned the special value "infinity", no tasks limit is applied. Defaults to 33%, which equals 10813 with the kernel's defaults on the host, but might be smaller in OS containers.

For my suspect PID (a lot of files) :

  • cat /proc/21890/status | grep Thread => 1 thread
  • ls /proc/21890/task | wc
  • confirmed by the usual command : ps -eLf | grep calrisk | wc

I have around 10805 threads running for a given JVM very close to the limit.

Complete guide :

https://www.journaldufreenaute.fr/nombre-maximal-de-threads-par-processus-sous-linux/

Parameters not present in all man page, it could grown up to 12288 on latest version.

To be check !

 

 

How-to extend Angular mat-table

Rédigé par gorki Aucun commentaire

Problem :

I would like to have a common table component that makes :

  • table, multicolumn
  • customize row renderer
  • sort
  • pagination
  • export
  • filtering

Well I'm using angular-material, not bad and with mat-table out of the box :

  • sorting : MatSort
  • pagination : MatPaginator
  • export : MatExporter with this extension

But integrate a filter (I try from the same author this one) was not as good as I wanted.

Solution :

After a few hours of googling, I found :

  • An extension : https://github.com/kerrexwong/ExtendedMatTable
    • But there wasn't the possibility to customize the content of the column
    • It was the source of the idea
  • A few stackoverflow talk about the same idea, but nothing working easily in Angular 11 or easy to use
    • https://stackoverflow.com/questions/62961776/is-it-possible-to-create-an-angular-material-mat-table-component-with-extra-dire
    • https://betterprogramming.pub/angular-material-build-your-own-generic-mattable-a49ba68a375a
  • Tried to copy MatTable and extends CDKTable but
    • _headerRowOutlet was always undefined in my copy

Finally from a more standard way :

  1. Create your own component
  2. It takes a few arguments :
    • functionalName : a functional name for the export. I put it in the filename, nothing to do with the display
    • datasource : not a MatTableDataSource, just an array of object
    • headers : the headers, an array of string, one per column
    • Sort must be at this level... Because the ng-container describing the column contains mat-sort-header for sorting... So we'll pass the the sort to the generic table.
<app-hpa-table [functionalName]="'a comprehensive name for export'" [dataSource]="array of object" [headers]="an array of string" [parentSort]="sort" matSort matSortActive="weight">
  1. A list of column definition. "name" is in the array 'headers'. Element comes from the array of objects.
        <ng-container matColumnDef="name">
            <th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
            <td mat-cell *matCellDef="let element"><div class="widget-list-name-column">{{element.name}}</div></td>
        </ng-container>
  1. The typescript part of the parent component
    1. ViewChild for sort should be static
@ViewChild(MatSort, {static: true}) sort: MatSort;
  1. The array of objects should be set in one line (not append object by object) to avoid to many update of the generic table

A bit long, I'll describe the generic component another time and try to make an online example.

Classé dans : Non classé Mots clés : aucun

OceanWP, Woocommerce and custom menu

Rédigé par gorki Aucun commentaire

Problem :

A wordpress site with OceanWP theme, Woocommerce plugin.

The requirement was to have 3 parts in the website :

  • Each parts has a different menu
  • Each parts has a different colors for menu and header

With OceanWP, you can set for each page : menu, custom header, colors...

A bit tedious to maintain from my point of view, but works, except for Woocommerce pages, especially categories.

Solution :

As everything in wordpress works with extensions, even OceanWP andWoocommerce have their own set of paid extensions... A world of business here (as 50% of the websites run wordpress...). Paid extension could be really usefull in some cases, for my simple task, I simply do it like that :

  1. Export OceanWP parameters
  2. Create a child theme of OceanWP and activate it
  3. Import OceanWP parameters
  4. Advantages :
    1. You can copy / paste of the parent theme in the child theme to modify it
    2. You can add custom functions
  5. Here is the main part, as OceanWP is very customizable (to authorize paid plugins), they already have a lot of hook ready
    1. ocean_custom_header_template : a hook to select the template
    2. ocean_custom_menu : a hook to select the menu

Adding hook to select the right theme for Woocommerce page :

function my_custom_header_function($template) {
       $result=$template; 
        if ( is_shop() || is_product() || is_product_category() ) {
          if ('<name-of-my-slug>' == get_queried_object()->slug) {
// Exception for one category
// We have created custom OceanWP header in OceanWP Theme Library, here is the ID (shown in the URL when editing the custom header)
              $result=10849;
          } else {
// All others categories have another header
              $result=10244;
          }
	}
	return $result;
}
add_filter( 'ocean_custom_header_template', 'my_custom_header_function' );

And for the menu :

function my_custom_menu($menu) {
        if ( is_shop() || is_product() || is_product_category() ) {
                if ('<name-of-my-slug>' != get_queried_object()->slug) {
                        // Except for one category, I return the custom menu to display
                        return '493';
                }        
        }
        return $menu;
}

add_filter( 'ocean_custom_menu', 'my_custom_menu');

Well, done, not perfect but done thanks to OceanWP possible customization and Wordpress ecosystem of paid plugins.

Could be done :

  • Suggest a pull request to OceanWP with an GUI to select the custom header/menu for a given slug
  • Select the custom header in a list instead of putting direct ID...

But no time today !

And I tried a mix of extensions :

But as everything, they are designed to work for a given use case and OceanWP+Woocommerce for categories was not in the scope.

Swing application freeze

Rédigé par gorki Aucun commentaire

Problème :

J'ai une application en client lourd java qui fonctionnait bien. Depuis quelques jours, elle freeze quand j'ouvre une série de popup ce qu'elle ne faisait pas avant (ou que je n'avais pas remarqué).

Précision : je suis sous Linux, Gnome.

Solution :

J'ai désactivé les agents que j'avais en même temps, supprimer les options inutiles de la JVM, toujours rien.

La stacktrace me dit ceci :

"pool-19-thread-1" #175 prio=5 os_prio=0 tid=0x00007fe2b4055000 nid=0x5ee3 waiting for monitor entry [0x00007fe3d2efd000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at java.awt.KeyboardFocusManager.clearMostRecentFocusOwner(KeyboardFocusManager.java:1882)
        - waiting to lock <0x00000000e081d6e0> (a java.awt.Component$AWTTreeLock)
        at java.awt.Component.disable(Component.java:1526)
        at javax.swing.JComponent.disable(JComponent.java:3639)
        at java.awt.Component.enable(Component.java:1515)
        at java.awt.Component.setEnabled(Component.java:1478)
        at javax.swing.JComponent.setEnabled(JComponent.java:2680)
        at javax.swing.JComboBox.setEnabled(JComboBox.java:1391)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

"SwingWorker-pool-4-thread-7" #171 daemon prio=5 os_prio=0 tid=0x00007fe33c6ff000 nid=0x5edf waiting on condition [0x00007fe3bbefb000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000fb81e808> (a java.util.concurrent.FutureTask)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:429)
        at java.util.concurrent.FutureTask.get(FutureTask.java:191)
        at org.GNOME.Accessibility.AtkUtil.invokeInSwing(AtkUtil.java:68)
        at org.GNOME.Accessibility.AtkObject.hashCode(AtkObject.java:234)
        at org.GNOME.Accessibility.AtkWrapper.emitSignal(Native Method)
        at org.GNOME.Accessibility.AtkWrapper$5.propertyChange(AtkWrapper.java:545)
        at java.beans.PropertyChangeSupport.fire(PropertyChangeSupport.java:335)
        at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:327)
        at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:263)

Au final, ce lien j'ai trouvé ce lien et j'ai ajouté l'option Java sur la ligne de commande. Tout est OK.

-Djavax.accessibility.assistive_technologies=

Pour plus d'informations :

https://docs.oracle.com/javase/8/docs/technotes/guides/access/new-features.html

Fil RSS des articles