Beware of this wordpress function


I am not sure how many of the developers note this when using this wordpress function, but if you didn't notice this, then you might end up with performance issues.





The function i am taking about is update_option.





Two arguments are required to invoke the function which is the option name and option value. The performance issue will happen if you don't specify the third argument to false. The third argument i am talking about is the autoload. By default it is set to true.





What is options autoload?





If the autoload is set to true, the option will be loaded on every request to wordpress. By default the value is true unless specified by the developer. Especially if you are using options to store a lot of data because the data you are storing are not related to posts. This will slow down wordpress. So take extra care for every update option calls, or you can define a custom function which sets this value as false and invoke it.


Share:

My first contribution to wordpress core


Yesterday i made my first contribution towards wordpress core ( its not merged yet ). In the past i have created an issue about the docs related to image size which is how i got this badge.





What was the fix about ?





When wordpress deletes a subsite, it drops all the tables related to the subsite. The issue is it doesnt consider there may be foreign key constraints in the external plugin tables. This leads to deleted site tables not being removed from db.





How i patched it ?





Before the fix, this is how the tables were dropped.





$wpdb->query( "DROP TABLE IF EXISTS `$table`" ); 




I change this line to





$wpdb->query( "SET FOREIGN_KEY_CHECKS=0; DROP TABLE IF EXISTS `$table`; SET FOREIGN_KEY_CHECKS=1;" ); 




at the time of writing this article, the fix is not merged to wordpress core.


Share:

Convert yaml to env variables in a single step


Sometimes you wanted to convert the yaml files in to env variables which will be used on docker-compose.yaml. I had a valid usecase where i had to set spring yaml variables from docker-compose.





To do that it usually involves the flattening of yaml keys, converting them to uppercase, then set the value





This requires some minutes of manual work. so i wrote a tool which does this automatically. you can find this tool here





https://naveen17797.github.io/flatten/





This converts the spring yaml properties to env variables. For example









This deflate the nested foo.bar.bas and converts to env variable FOO_BAR_BAS.


Share:

Running your wordpress site on github


Running a wp instance requires you to pay for hosting. Even though you publish occasionally you need to keep the instance to running. What you can do is to build static html, css webpages. There are several builders available which does this. But you will miss wp customization and several other features in those static site builders.





To solve this issue, i created gitpress.





https://github.com/naveen17797/gitpress





This allows you to run the wordpress site locally and when you publish the posts it converts your wordpress site to static html and pushes to github pages.





This makes uses of two components






  1. Docker




  2. Simply Static wordpress plugin





The docker is very helpful to run the wordpress instance across mutliple platforms. The simply static plugin is used for converting the site to static html.





You can download gitpress from here





https://github.com/naveen17797/gitpress





here is the live example for github in action





https://naveen17797.github.io/


Share:

I hate methods/functions returning multiple types


Basically the title.





i always see these functions like





function f1 ( $a1, $a2, $a3 ) {

if ( $a1 ) {
return false;
}

if ( $a2 ) {
return 'some string';
}

return array('some data');


}




When the code returns multiple types from a single function it automatically becomes code smell.





Because whenever i want to use this function f1, i would need check the type it returned.






$result = f1( $a1, $a2, $a3 );


if ( is_array($result ) ) {
// do thing 1
}
elseif ( is_string($result) ) {
// do thing 2
}
else {
// do thing 3
}




just to use this function i would need 6 lines of code. 6 lines of code everywhere where i need to use the function. As a developer i would hate to use this function anywhere, because everywhere i would need to handle 3 flows.





But i get your intention, what happens when the value doesn't match function expectation in run time. You can avoid this by either






  • Throwing exceptions




  • Creating objects to represent invalid states





Throwing exceptions





Throwing exceptions is usually helpful, because i could handle all the exceptions which arise in the block of code with the single try catch block.





function f1($a1, $a2, $a3 ) {
if ( ! $a1 || !$a2 ) {
throw new Exception('something terrible happened');
}
return array('some data');
}




Creating objects to represent invalid states





lets say you have a function which returns subscription by id and the interface for subscription looks like this.





interface Subscription {

function get_id();


}




and the function looks like this.





function get_subscription_by_id ( $id ) {
if ( ! $id ) {
throw new Exception("subscription id is not valid");
}

return Subscription_Factory::get($id);
}




I could create a object which represent invalid subscription and return it instead of throwing exception






class Invalid_Subscription implements Subscription {

function get_id() {
// do nothing.
}

}




now one might ask how to handle this state, i prefer to handle it inside a factory.





Lets say i get a subscription and i call an api. in that that logic would be inside the factory method





class Request_Factory {

// request class has execute() method which sends the request.

static function get($subscription) {

if ( ! $subscription instance of Valid_Subscription ) {
return Invalid_Request();
}

return Valid_Request();


}

}




now lets see how the usage would look like.





Request_Factory::get( Subscription_Factory::get(2) )->execute();




we have eliminated all the ifs, they are delegated to factories.





Let me know your thoughts on the comments.


Share:

Testing spring webclient without spring context


Spring webclient is an important component in the spring framework. Its highly customizable, allows us to do perform all the http operations in a declarative way.





But the check is you cant unit test the spring webclient. To perform assertions you would likely need to use wiremock which takes a lot of time for the tests to initialize and run. This affects the motivation to perform the test driven development.





so i decided to write my own library which allows me to perform assertions on webclient call






public WebClient build() {
WebClient.Builder builder = this.builder
.clientConnector(
new FakeHttpConnector(requestResponsesList)
)
.exchangeFunction(ExchangeFunctionFactory.getInstance(this));

if (baseUrl != null) {
builder.baseUrl(baseUrl);
}

return builder.build();
}




The above snippet of code is from the library. I perform the assertions by writing a custom http connector and a exchange function to perform assertions.





How can i use it ?





it available via maven, add the below to the pom.xml file






<dependency>
<groupId>io.github.naveen17797</groupId>
<artifactId>fakewebclient</artifactId>
<scope>test</scope>
</dependency>




Lets say i want to test a post request to www.google.com, i could perform assertions like this





FakeWebClientBuilder fakeWebClientBuilder = FakeWebClientBuilder.useDefaultWebClientBuilder();

FakeRequestResponse fakeRequestResponse = new FakeRequestResponseBuilder()
.withRequestUrl("https://google.com/foo")
.withRequestMethod(HttpMethod.POST)
.withRequestBody(BodyInserters.fromFormData("foo", "bar"))
.replyWithResponse("test")
.replyWithResponseStatusCode(200)
.build();



WebClient client =
FakeWebClientBuilder.useDefaultWebClientBuilder()
.baseUrl("https://google.com")
.addRequestResponse(fakeRequestResponse)
.build();


assertEquals("test", client.method(HttpMethod.POST)
.uri(uriBuilder -> uriBuilder.path("/foo").build())
.body(BodyInserters.fromFormData("foo", "bar"))
.exchange().block()
.bodyToMono(String.class).block());

Assertions.assertTrue(fakeWebClientBuilder.assertAllResponsesDispatched());




simple isn't it ? No more waiting for wiremock to initialize.





If you find it helpful, you can star this repo on github





https://github.com/naveen17797/fakewebclient


Share:

How to use the action scheduler to run a long running task?


If you are looking to run a Task T which cannot be split in to units, then you can stop reading right here. The ability to run long running task until it completes is restricted by hosting provider. But in this article I will show you how to process large number of items by creating a action scheduler queue.





What action scheduler allows us to do?





By default it doesn't implement any queuing system to run a long list of operations. The two methods available are






  • Create a single action A which will run on future




  • Create a repeating action R which will be called continuously.





We need to design the queue considering these constraints.Lets say i have 1000 posts to be processed, i can process 5 posts without timeout everytime, then we have to enqueue 1000 / 5 = 200 actions in action scheduler.





The process of enqueuing actions can also timeout the php runner which was the initial problem we wanted to overcome.





My solution is to simply enqueue the actions one by one inside the handler method. Lets say i have actions A1 ( offset = 0, limit = 5) , A2 ( offset = 5, limit = 5). I am not going to enqueue A2, i will enqueue it once the A1 completes.





Enough Theory, Show Me The Code!





<?php

function start() {
// Note that we add only A1 here.
as_enqueue_async_action( 'my_hook', array( 'offset' => 0, 'limit' => 5, 'count' => 1000 ), 'my-group');
}



add_action('my_hook', function ( $args ) {

// do_some_action($args);


// Lets assume we did some work with $args. Now update the offset.
$args['offset'] = $args['offset'] + $args['limit'];

if ( $args['count'] < $args['offset']) {
// process is complete, return early.
return;
}

// we still need to run the process, enqueue another action.
as_enqueue_async_action( 'my_hook', $args );

});




with this simple trick you process a large list of items without worrying about timeout. The only disadvantage of enqueuing next action on the executed action is that we can't leverage the concurrency provided by action scheduler.


Share:

This one php operator you didnt knew about


we all knew when you want to execute shell commands in php we have a list of functions like shell_exec, exec, popen, etc to execute the code





<?php echo shell_exec('ls'); ?>




but today i came to knew about the backtick operator which does the same





<?php echo `ls`; ?>




The backtick operator (``) in PHP is used to execute shell commands. It is similar to the shell_exec() function, but it allows you to use command substitution, which means that you can include the output of a command inside another command by enclosing the command that you want to execute in backticks.





In general, the backtick operator is most useful when you want to execute a shell command and capture the output of the command for further processing in your PHP script.


Share:

How can i use async pipe to handle click or other user event ?


Almost all of the tutorials related to async pipe is related to loading data from api. But there is another thing you can do with it. Lets say you have a button which sends some data to api. The imperative code would look something like this





@Component({
selector: 'app-root',
template: `<button (click)="click()"></button>`,
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'test';

click() {
this.apiService.send()
.pipe(take(1)) // complete upon first emission
.subscribe(() => {})
}
}




That is, its creating a new subscription every click and completes. And if you forget to use take(1) operator you would be creating multiple subscriptions. The clean way of doing this would be to create an subject and subscribe with async pipe.





@Component({
selector: 'app-root',
template: `<ng-container *ngIf="clickStream$|async"></ng-container> <button (click)="this.clickStream.next(true)"></button>`,
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'test';

clickStream = new Subject();
clickStream$ = this.clickStream.asObservable()
.pipe( concatMap(() => this.apiService.send()) )

}




This snippet of code doesn't create new subscription per every click. The subscription for click event is removed when the component is destroyed.


Share:

RxJs: How to handle errors in infinitely emitting observable


Lets say i have a button which sends an api request to external server when clicked. The api requests may fail occasionally, we would want the observable to keep running even though a failure has occurred on the pipeline.





lets use this example





import {
fromEvent,
scan,
map,
of,
catchError,
EMPTY
} from 'rxjs';

let i = 0;

fromEvent(document, 'click').pipe(map(() => {
i += 1;
if (i % 2 === 0) {
throw new Error('an error occured')
}
return i;
}), catchError(() => EMPTY)).subscribe({
next: (count) => console.log('Clicked ' + count + ' times'),
error: (error) => console.log('error occured'),
complete: () => console.log('completed')
});





This will print this output upon click






Clicked 1 times





completed






As you can see if we catch an error and return EMPTY observable the subscriber completes. i want to prevent this from happening, i want it to listen to infinite click events and it should not complete.





introducing retry method ..





By definition it does the following






Returns an Observable that mirrors the source Observable with the exception of an error.


https://rxjs.dev/api/index/function/retry




so when an error occurs we just call retry() with no arguments. It is important to note that using the retry operator with no arguments can cause the observable to retry indefinitely, which can be problematic if the error is not recoverable. In such cases, it is generally better to use the catchError operator to handle the error and continue the sequence with a new observable, or to use the retry operator with a finite number of retries.





import {
fromEvent,
retry,
map,
} from 'rxjs';

let i = 0;

fromEvent(document, 'click').pipe(map(() => {
i += 1;
if (i % 2 === 0) {
console.log('error occured for click count: ' + i)
throw new Error('an error occured')
}
return i;
}), retry()).subscribe({
next: (count) => console.log('Clicked ' + count + ' times'),
error: (error) => console.log('error occured'),
complete: () => console.log('completed')
});





This subscriber will continue listening to click events even when error occurs, here is an example output from this setup





Clicked 1 times
error occured for click count: 2
Clicked 3 times
error occured for click count: 4
Clicked 5 times
error occured for click count: 6
Clicked 7 times
error occured for click count: 8
Clicked 9 times
error occured for click count: 10
Clicked 11 times
error occured for click count: 12

Share: