What event is fired when Laravel app is being shutdown? - laravel

Specifically what I am doing is in my AppServiceProvider->boot() method I am creating a singleton class like below:
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
$this->app->singleton('App\Support\PushNotificationHelper', function ($app) {
return new PushNotificationHelper();
});
}
}
The helper class is needed for a Queue worker job I use for Pushing Notifications to mobile apps. When the mobile device is an Apple device I need to establish a curl connection and have the connection persist beyond the life of the queue worker job. This is why I am using the singleton to hold the connection like:
class PushNotificationHelper {
protected $http2Connection;
protected $http2Expire ;
public function getConnection($options) {
$this->http2Connection = curl_init();
curl_setopt_array($this->http2Connection, $options);
return $this->http2Connection;
}
Apple claims if I connect and disconnect repeatedly then they will issue a Denial of Service (DOS). My app literally sends 1000s of notifications per hour. When ever I use the connection I check for errors and will close/reopen the connection when needed like:
curl_close($http2Connection);
However I would like to know how I can detect when the app will close for good so I can gracefully close the connection. If there is no way to do this will it harm my server over time by leaving open connections hanging, lets say months of running if the app was to start/stop several times a day ?
Another option could be is there a curl option to tell the connection to auto disconnect after so much time. (I force a close and reopen every 4 hours) so if I could tell connection to auto-close after 5 hours at least then maybe it would be self-cleaning?

IMHO you can try to add a terminating callback to your app instance, for example in the AppServiceProvider, i.e.:
public function boot()
{
$this->app->terminating(function () {
// your terminating code here
});
}

You can use the boot method for anything.
From laravel docs:
This method is called after all other service providers have been
registered, meaning you have access to all other services that have
been registered by the framework
The key is that boot method run when all services are registered, so, you can inject services in the boot method definition.
public function boot(SomeService $someService, OtherService $otherService)
{
$someService->doSomething();
$otherService->doSomething();
}
In my opinion, you must to use this method to run code required by your app in all contexts: user logged in, user logged out, post, get, put, etc., etc.

Related

How to check If the current app process is running within a queue environment in Laravel

I applied a global scope to my models via a trait, but I don't want the global scope applied when the model is called/processed from my Redis queue.
How do I detect if the current instance is a queue process? just like we have this
if (App::environment('local')) {
// The environment is local
}
to detect if the app is running in local or production.
Simply call the runningInConsole() method :
if (app()->runningInConsole()) {
or with the App facade:
if (\App::runningInConsole()) {
to check if execution is happening via CLI.
I have 2 solutions for this. Both work in Laravel 9.
First one
Larvel registers \Illuminate\Queue\CallQueuedHandler in the service container if the app is running in the queue, it does not register that class when running in the console or with a web request. So the following check works and distinguishes between the queue and running on the console.
// true when code is in the queue
app()->resolved(\Illuminate\Queue\CallQueuedHandler::class);
Second one
When Laravel starts a Queue Job there is an event with a callback you can use to attach some currently-running-in-queue flag in the service container.
// Within the boot method of a service provider
App::bind('processing-job', function ($app) {
return false;
});
Queue::before(function (JobProcessing $event) {
App::bind('processing-job', function ($app) {
return true;
});
});
Then you can run a check anywhere like this:
App::get('processing-job');
Note
When running tests, and env var QUEUE_CONNECTION is set to sync the test will think you are in a queued process. This is because when working in sync both your test and the job live within the same instance.

NET Core Server Side multiple session Blazor

I'm trying to host my Blazor application on my server.
I spent all the summer on it and I just realized every time I open my website on new device it doesn't create a new session restarting from zero, but continues where I left it. The worst part is there is a login system behind it, so I feel super dumb at the moment.
I really need a big hint on how to fix this "not little" issue.
Is there a way to make server create new session every time someone open the website (without making it loose to other users)?
The solution should be use a Client Template instead, but the performance are really to slow.
UPDATE:
Accounts "user password" are:
- user user
- test test
Download project sample (requires Net Core 3.0)
[SOLUTION] itminus found the solution to my issue.
You have also to add in ConfigureServices in Startup.cs this services.AddScoped<Storage>();
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddScoped<Storage>();
}
every time I open my website on new device it doesn't create a new session restarting from zero, but continues where I left it.
I checkout your code and find that you're using Singleton Pattern to initialize the Storage. If I understand it correctly, this Storage singleton instance will be shared across different users (also across different devices). As this instance will be used to render the Main.razor page, there will be concurrency problems that you're experiencing now .
To fix that issue, the Storage instance should be limited within some specific connection. As you're using Blazor Server Side, you could register the Storage as a Scoped Service:
In Blazor Server apps, a scoped service registration is scoped to the connection. For this reason, using scoped services is preferred for services that should be scoped to the current user, even if the current intent is to run client-side in the browser.
Firstly, remove the static singleton instance :
public class Storage
{
private static Storage instance;
private Storage()
{
}
public static Storage GetInstance()
{
if (Storage.instance == null)
Storage.instance = new Storage();
return Storage.instance;
}
public List<Items>list {get;set;} = new List<Items>();
public string password {get;set;}
}
Register this Class as a scoped service:
services.AddScoped<Storage>();
And then inject this service in your Login.razor and Main.razor :
#inject project.Storage Storage
Finally, you need change all the Storage.GetInstance(). to Storage.:
Storage.list = Order;
...
Storage.password = password;
I notice that you're also creating the Importer/Additional instance using the Singleton Pattern. I would suggest you should refactor them to use Service Injection in a similar way.

Xamarin Bound Service Connection method can I instantiate a class

I am trying to understand bound services. I have an xamarin app using mqtt and the mqtt is getting disrupted during the activity lifecycle. Currently I have a connection class that handles the connection to the mqtt that is called from an activity.
I need the connection class to run without interruption regardless if app is in foreground background etc. (if anyone is curious the keepalive routine gets interrupted when the app goes into the background) The app is 100% stable if I don't let the phone go to sleep (developer option stay awake while charging). If I let the phone go to sleep after a while the mqtt gets disconnected.
So from what I am understanding I need a boundService, boundServiceBinder, and boundServiceConnection classes.
It looks like I want the heavy lifting to happen in the boundServiceConnection class.
Example
class BoundServiceConnection : Java.Lang.Object, IServiceConnection
{
Connection connect;
public void OnServiceConnected(ComponentName name, IBinder service)
{
connect = new connection();
}
public void OnServiceDisconnected(ComponentName name)
{
}
}
Now will this work, will I be able to access the properties of the connection class as I am able to when I instantiate in an activity?
Thanks all
Mark
Yes you can,
what you want to do is just create a method in you boundServiceConnection class that instantiates the object. and call it after you have bound to the service

unable to connect to back4app using parse4cn1 lib

Good day all, I tried connecting to the back4app back end service using the new parse4cn1 lib .....I supplied the keys required but my app could not connect to the backend for some strange reasons.kept reporting (unable to connect to back end.........codename one revisions some long numbers)
Some help or direction will be appreciated.Thanks all
What keys are you using? You need to pass your App Id and Client Key to parse4cn1. I just ran the regression tests against back4app and I didn't get any connection error. Can you provide more details (e.g. a dump) of the error you're getting?
Where are you putting your Parse.initialize? Just went for some digging on parse4cn1 and it seems that it needs to be inside a "initVars" function, usually created within a state machine as you can see in the example below:
public class StateMachine extends StateMachineBase {
/**
* this method should be used to initialize variables instead of
* the constructor/class scope to avoid race conditions
*/
protected void initVars(Resources res) {
Parse.initialize(API_ENDPOINT, APP_ID, CLIENT_KEY);
}
}
Maybe that can help you on this connection issue. Also check the link below (A very useful guide) for further info:
https://github.com/sidiabale/parse4cn1/wiki/Usage-Examples

How to clear database entries on browser close in jsf?

In our application which makes
use of JSF/PrimeFaces, Spring and Hibernate once a user logs in, we set a flag in the DB until the user logs out from the application or the session expires. The problem is, we need to clear this flag in the DB even when he simply closes the browser without proper logout. To acheieve this, I have already tried jquery $window.unload and $window.bind functions which actually invokes some JS function which is associated with <p:remoteCommand> which in turn invokes a managed bean method to clear the DB. However, I later came to know this is not reliable and while testing also we saw the event was not firing consistently. How can I achieve the DB cleanup anyway?
Listening on browser close is not reliable. You can use beforeunload event for that, but this is not supported on every webbrowser the world is aware of and even disableable/spoofable/hackable by the enduser. Then we're not talking about the race condition during firing the ajax request: would the ajax request arrive in its entirety right before the browser is closed? More than often this is not the case and the browser close wins over the ajax request.
Just listen server side on session expiration instead.
#WebListener
public class MyHttpSessionListener implements HttpSessionListener {
#Override
public void sessionCreated(HttpSessionEvent event) {
// NOOP.
}
#Override
public void sessionDestroyed(HttpSessionEvent event) {
HttpSession session = event.getSession();
// Do your job here.
// ...
}
}
Note that this is also invoked when you explicitly invoke ExternalContext#invalidateSession() (or HttpSession#invalidate()) during programmatic logout.

Resources