How to know that ionic app going to closed or killed in ionic 3? - ionic2

Is there any way to know that our ionic app is getting closed or killed?

You can subscribe to the pause event of the Ionic platform service. The docs describe the pause event like this:
The pause event emits when the native platform puts the application
into the background, typically when the user switches to a different
application.
David M. gave a good answer on how to implement this here:
import { Component } from '#angular/core';
import { Subscription } from 'rxjs';
import { Platform } from 'ionic-angular';
#Component({...})
export class AppPage {
private onPauseSubscription: Subscription;
constructor(platform: Platform) {
this.onPauseSubscription = platform.pause.subscribe(() => {
// do something when the app is put in the background
});
}
ngOnDestroy() {
// always unsubscribe your subscriptions to prevent leaks
this.onPauseSubscription.unsubscribe();
}
}
First of all, you'll have to inject the Platform service into your page/component and then you can subscribe to the pause event. I only edited Davids code sample slightly, so please give him some credit.
Ionics Platform service is merely a wrapper around Cordovas events. So if you're further interested, check out the Cordova docs on events or the pause event.

Related

Apollo GraphQL unsubscribe seems to be broken

We are using Apollo GraphQL with subscriptions (via websockets) in a node.js backend and a react frontend.
The app provides a list of devices. When a user clicks on one device he gets the monitoring data for the device with live updates (from the subscription). When the user clicks on another device the subscription is stoppen, the data for the next device is being loaded and subscribed.
I pasted the messages from the websocket connection below. I first tried to paste the raw log here, but the screenshot is much easier to read.
Please ignore the ids 1-5. Important for my problem is id 6 and 7. The id is created when clicking on the first device (at 11:15:35) and then the details are closed so the subscription is stopped (at 11:15:36). Now the user clicks another device and starts subscription 7. Some seconds later the system pushes data for both, the 6th and 7th subscription.
Is there something I can do so "stop" actually means "stop" or is this a bug?
Edit: as requested, here is the code I use to subscribe/unsubscribe (I had to cut some parts due to company regulations)
const subscription = useRef(null)
const { loading, data, error, subscribeToMore } = useQuery(getDevice, { variables: { deviceId } })
useEffect(() => {
return () => {
if (!subscription.current) return
subscription.current()
subscription.current = null
}
}, [deviceId])
if (!subscription.current) {
subscription.current = subscribeToMore({
document: geDeviceSubscription,
variables: {
deviceId
},
updateQuery: (prev, { subscriptionData }) => ({ device: subscriptionData.data.subscribeDevice })
})
}
Edit 2: It is for sure not my clients issue as it also happens if the use the GraphiQL gui, start a subscription and stop it again. The new data is not displayed but it is visible in the websocket connection in the network tab of the browser (chrome).
It seems to have been a bug in an older apollo graphql or nestjs-apollo-graphql version (We use those frameworks in the backend). After upgrading all the backend dependencies to "latest", the bug doesn't seem to persist.

Loopback 4: Scheduled cron example using Loopback 4

As I am very new with loopback 4 and Typescript, knowing that we have to use custom booter to implement schedule tasks like Cron.
I require a code snippet which does that, i.e A custom booter class that implements Booter phases of configure, discover and load to Run a Cron
I am not sure this is the way to do it, but this is working for me.
https://loopback.io/doc/en/lb4/Booting-an-Application.html#bootcomponent
Start with creating a component inside the project folder. I created src\components\cron.component.ts
import { Component } from "#loopback/core";
import { CronJob, CronCommand } from "cron"
export class CronJobsComponent implements Component {
private cj: CronJob;
constructor(){
this.start()
}
async start(){
this.cj = new CronJob('* * * * * *', this.showMessage)
this.cj.start();
}
showMessage:CronCommand = async () => {
console.log("inside cron jobs")
}
}
Next import our component in the application.ts file
import { CronJobsComponent } from './components'
and register our new component inside the constructor
this.component(CronJobsComponent);
The corn job starts on application boot.
I used https://www.npmjs.com/package/cron and https://www.npmjs.com/package/#types/cron
Hope this helps you.
You can always create a cron endpoint.
http://localhost:3000/cron
You could then add a curl command to your crontab.
curl http://localhost:3000/cron
This method is a great way to handle seperation of concerns. If your api is a microservice running on kubernetes, you could call the cron endpoint using the Cron resource.
Just make sure that the endpoint is secure if your application is public.

The azure continuous webjob is running but sometime it was stopped/restarted unexpectedly

Our application is using a webjob to generate the data, for a moment we are facing a problem that is sometime it was stopped/restarted unexpectedly when it is processing the messages queue. It leads to our webjob don't know when it is forcing restarting/stopping to mark which data were processed then let the webjob restart/stop afterward.
Is there any idea to get the stopping/restarting notification to synchronize data?
Many thanks!
If you're using queues, a restarting webjob shouldn't cause you to have any data loss. Since the message will not be completed, it will be put back on the queue for (re)processing.
As far as the restarting goes: make sure you don't have any scenario's in code that break the webjob completely.
Add Application Insights and add an alert for the specific case you're looking for.
See Set Alerts in Application Insights
Sometimes webjobs can get killed by scale-in procedures. You can make sure they have a graceful death by listening to the shutdown event by using the class Microsoft.Azure.WebJobs.WebJobsShutdownWatcher in nuget package Microsoft.Azure.WebJobs.
As in version 1.1.2 of the nuget package:
public sealed class WebJobsShutdownWatcher : IDisposable
{
// Begin watching for a shutdown notification from Antares.
public WebJobsShutdownWatcher();
// Get a CancellationToken that is signaled when the shutdown notification is detected.
public CancellationToken Token { get; }
// Stop watching for the shutdown notification
public void Dispose();
}
A way to use this: in your webjob Program.cs class you get a cancellation token and write the code you want to be executed when shutdown happens.
private static void Main()
{
...
var cancellationToken = new WebJobsShutdownWatcher().Token;
...
cancellationToken.Register(() =>
{
//Your data operations here
});
...
}
Thank Diana for your information. I tried this approach but it was not work very well, webjob is just waiting for 5 seconds before restarting/stopping although I set 60 seconds in the settings.job file. Here is my code below
static void Main()
{
var config = new JobHostConfiguration();
var host = new JobHost();
var cancellationToken = new WebJobsShutdownWatcher().Token;
cancellationToken.Register(() =>
{
//Raise the signal
});
// The following code ensures that the WebJob will be running continuously
host.RunAndBlock();
}

How to intercept AWS SNS messages to iOs mobile endpoints in Xamarin?

The documentation on AWS -SNS for use of SNS within Xamarin iOS projects shows how to register an iOS device to receive messages from SNS, but not clear how to intercept those messages within the application and programtically respond to the message. How do I capture the incoming message, and process appropriately rather than just showing the text of the message received? Is this done by sending a different message than is shown in the AWS console, and where can I intercept it in my application?
This is the example I've been following:
public override bool FinishedLaunching(UIApplication app, NSDictionary options) {
// do something
var pushSettings = UIUserNotificationSettings.GetSettingsForTypes (
UIUserNotificationType.Alert |
UIUserNotificationType.Badge |
UIUserNotificationType.Sound,
null
);
app.RegisterUserNotifications(pushSettings);
app.RegisterForRemoteNotifications();
// do something
return true;
}
public override void RegisteredForRemoteNotifications(UIApplication application, NSData token) {
var deviceToken = token.Description.Replace("<", "").Replace(">", "").Replace(" ", "");
if (!string.IsNullOrEmpty(deviceToken)) {
//register with SNS to create an endpoint ARN
var response = await SnsClient.CreatePlatformEndpointAsync(
new CreatePlatformEndpointRequest {
Token = deviceToken,
PlatformApplicationArn = "YourPlatformArn" /* insert your platform application ARN here */
});
}
}
Here is the message I'm sending:
{
"APNS_SANDBOX":"{\"aps\":{\"alert\":\"This is my message\"}}"
}
This seems to work fine for displaying a text message sent from the AWS console, whether the app is running or not, but that's not what I need for my app. (e.g. a chess app, where the SNS messages are used to exchange moves made by a pair of users and the app displays them.)
The FinishedLaunching method contains several not altogether helpful "do something" , but I can't figure out how to, say call some method in my PCL when a particular message is received and pass the content of the message to that method.
You can subscribe the DidReceiveRemoteNotification() event in AppDelegate.cs to get your content you sent on SNS.
public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
{
// retrieve something from a server somewhere
}
This event will trigger when user taps the notification to open the app and when this app is on background state or foreground state.
If this app is closed this event will not trigger, but we can also get the content in public override bool FinishedLaunching(UIApplication app, NSDictionary options) with the parameter options.
Moreover if you want to get it in PCL, we can make a MessagingCenter to achieve this:
Send content on native platform:
MessagingCenter.Send<object, NSDictionary>(this, "Notification", userInfo);
Then receive this MessagingCenter on PCL somewhere you like:
MessagingCenter.Subscribe<object, NSDictionary>(this, "Notification", (sender, dic) =>
{
});

Locking console batch process in Yii2

I'm developing a web application based on the Yii2 framework.
Every 12 hours the application needs to run a batch process to update some DB tables and it takes 5-10 seconds. In order to do that, I created a console command (say ./yii dummy/index) that is called by the windows task scheduler using a .bat script. However, while running the task, the application Web GUI is still running. Does Yii2 autonomously stops any web interaction while executing the task or should I lock manually the system to avoid any inconsistency issues? If is that so, how can I stop web interaction while executing the console process and restart them when it's completed?
Console and web apps are completely autonomous. Running a console command will in no way prevent the web app from running.
The easiest way to solve this problem would be to set some kind of mutex in your console command and check for it in your web application. For that, Yii2 offers a variety of mutex classes all derived from yii\mutex\Mutex.
You add a mutex to your console and web app configs:
'mutex' => [
'class' => 'yii\mutex\MysqlMutex',
],
In your console command you need to acquire the mutex (allow it to wait for a few seconds):
$mutexResult = Yii::$app->mutex->acquire('example-mutex', 10);
if ($mutexResult) {
echo 'Could not acquire lock'.PHP_EOL;
Yii::$app->end();
}
And when you're done, release it:
Yii::$app->mutex->release('example-mutex');
In your web application you then check if the mutex is available. I believe current application template will generate controllers that extend the yii\web\Controller class. You should create your own base controller class that extends yii\web\Controller and define its beforeAction method:
class BaseController extends \yii\web\Controller
{
public function beforeAction($action)
{
$mutexResult = Yii::$app->mutex->acquire('example-mutex', 20);
if ($mutexResult) {
Yii::$app->mutex->release('example-mutex');
} else {
echo 'Console app is running';
return false;
}
return parent::beforeAction($action);
}
}
Then extend all your web application's controllers from this BaseController class.
This way Yii will check for this flag before any action is executed.