Amazon EC2 terminated instance (Free Tier) - amazon-ec2

I am using free tier on Amazon. I had one micro instance, which I terminated. If I create another one (micro) instance, will Amazon start charging me?
I can still see my terminated instance in the instances list, but I cannot start or reboot it. Can I somehow delete it from the list?

You cannot perform any operations on the terminated instance. It is displayed in the list until one hour after deletion. After that time it will be removed from the list.

AWS charges you only for instances that are running, and as long as you only have one running at any one time you will not be charged. And NO operations can be performed on terminated instances, which disappear 1 hr after terminated.
UPDATE: There was a Price change
Now free tier gets you a "micro instance" for 750hrs/mo for 12 months. Over 750hrs or after 1 yr, not free. And as these posts get old, probably best to just look it up yourself here:
http://aws.amazon.com/ec2/pricing/

try this...
var terminateInstancesRequest = new TerminateInstancesRequest();
terminateInstancesRequest.InstanceIds = new List<string>() { InstanceId };
bool isError = true;
while (isError)
{
try
{
amazonEc2client.TerminateInstances(terminateInstancesRequest);
isError = false;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message + "\n" + ex.StackTrace);
isError = true;
}
}

Related

Caching is working for one hour while it should be for days

I have created an API using .NETCore 2.0 ; This API is connected to an oracle database to retrieve needed data; One of the functions takes too much time so I decided to use caching in order to retrieve data faster;
Function description: Get ranking
Caching period: Data should be renewed in cache memory each Monday
I am using IMemoryCache, but the problem is that data is not being cached for multiple days; It lasts only for one hour, after that data is being retrieved from database and takes too much time (10 s.); Below is my code:
var dateNow = DateTime.Now;
int diff = 7; // if today is Monday then should add 7 days to get next Monday date
if (dateNow.DayOfWeek != DayOfWeek.Monday) {
var daysToStartWeek = dateNow.DayOfWeek - DayOfWeek.Monday;
diff = (7 - (daysToStartWeek)) % 7;
}
var nextMonday = dateNow.AddDays(diff).Date;
var totalDays = (nextMonday - dateNow).TotalDays;
if (_cache.TryGetValue("GetRanking", out IEnumerable<GetRankingStruct> objRanking))
{
return Ok(objRanking);
}
var dp = new DataProvider(Configuration);
var response = dp.GetRanking(userName, asAtDate);
_cache.Set("GetRanking", response, TimeSpan.FromDays(diff));
return Ok(response);
Could be related to the token life Time since it's only 1 hour?
Firstly - have you tried checking to see if your worker process is being restarted? You don't specify how you are hosting your application but, obviously, if the application (worker process) is restarted your memory cache will be empty.
If your worker process / process is restarting then you could load the cache on start up.
Secondly - I believe that the implementation may choose to empty the cache due to inactivity or memory constraints. You can set the priority to never remove - https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.caching.memory.cacheitempriority?view=dotnet-plat-ext-3.1
I believe you can set this by passing a MemoryCacheOptions object to the constructor of the memory cache https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.caching.memory.memorycache.-ctor?view=dotnet-plat-ext-3.1#Microsoft_Extensions_Caching_Memory_MemoryCache__ctor_Microsoft_Extensions_Options_IOptions_Microsoft_Extensions_Caching_Memory_MemoryCacheOptions__.
Finally - I assume you've made your _cache object static so it is shared by all instances of your class. (Or made the controller, if that's what it is, a singleton).
These are my suggestions.
Good luck.

How to get IMEI number from Android device on first time install of Application using IONIC 3

I want to fetch IMEI number of Android device using Ionic 3.
I am using below code to fetch that by following this link.https://ionicframework.com/docs/native/uid/.
async getImei() {
const { hasPermission } = await this.androidPermissions.checkPermission(
this.androidPermissions.PERMISSION.READ_PHONE_STATE
);
if (!hasPermission) {
const result = await this.androidPermissions.requestPermission(
this.androidPermissions.PERMISSION.READ_PHONE_STATE
);
if (!result.hasPermission) {
throw new Error('Permissions required');
}
// ok, a user gave us permission, we can get him identifiers after restart app
return;
}
return this.uid.IMEI
}
I am calling the above method in constructor like this.
this.getImei();
Then i just want to print that console.
console.log("IMEI Number" + this.uid.IMEI);
Here I am facing one problem.For the first time when i am installing application on device, it is asking for permission , but in console am not getting any value.
When i am closing the Application,clearing from backstack, And then when I am opening the Application again that time I am getting value.
Can anyone please help me how to get value on First time installation.
It looks like you are first checking the permission. If the user doesn't have it (which will always be the case when you start it for the first time), you go into the if. Inside you request the permission, but after the user gives you permission, you just do return; without any value. So it will return nothing.
The second time you are starting the app, you already have the permission and it skips the if and goes directly to return this.uid.IMEI
So you should return the first return; to return this.uid.IMEI

Firestore transaction produces console error: FAILED_PRECONDITION: the stored version does not match the required base version

I have written a bit of code that allows a user to upvote / downvote recipes in a manner similar to Reddit.
Each individual vote is stored in a Firestore collection named votes, with a structure like this:
{username,recipeId,value} (where value is either -1 or 1)
The recipes are stored in the recipes collection, with a structure somewhat like this:
{title,username,ingredients,instructions,score}
Each time a user votes on a recipe, I need to record their vote in the votes collection, and update the score on the recipe. I want to do this as an atomic operation using a transaction, so there is no chance the two values can ever become out of sync.
Following is the code I have so far. I am using Angular 6, however I couldn't find any Typescript examples showing how to handle multiple gets() in a single transaction, so I ended up adapting some Promise-based JavaScript code that I found.
The code seems to work, but there is something happening that is concerning. When I click the upvote/downvote buttons in rapid succession, some console errors occasionally appear. These read POST https://firestore.googleapis.com/v1beta1/projects/myprojectname/databases/(default)/documents:commit 400 (). When I look at the actual response from the server, I see this:
{
"error": {
"code": 400,
"message": "the stored version (1534122723779132) does not match the required base version (0)",
"status": "FAILED_PRECONDITION"
}
}
Note that the errors do not appear when I click the buttons slowly.
Should I worry about this error, or is it just a normal result of the transaction retrying? As noted in the Firestore documentation, a "function calling a transaction (transaction function) might run more than once if a concurrent edit affects a document that the transaction reads."
Note that I have tried wrapping try/catch blocks around every single operation below, and there are no errors thrown. I removed them before posting for the sake of making the code easier to follow.
Very interested in hearing any suggestions for improving my code, regardless of whether they're related to the HTTP 400 error.
async vote(username, recipeId, direction) {
let value;
if ( direction == 'up' ) {
value = 1;
}
if ( direction == 'down' ) {
value = -1;
}
// assemble vote object to be recorded in votes collection
const voteObj: Vote = { username: username, recipeId: recipeId , value: value };
// get references to both vote and recipe documents
const voteDocRef = this.afs.doc(`votes/${username}_${recipeId}`).ref;
const recipeDocRef = this.afs.doc('recipes/' + recipeId).ref;
await this.afs.firestore.runTransaction( async t => {
const voteDoc = await t.get(voteDocRef);
const recipeDoc = await t.get(recipeDocRef);
const currentRecipeScore = await recipeDoc.get('score');
if (!voteDoc.exists) {
// This is a new vote, so add it to the votes collection
// and apply its value to the recipe's score
t.set(voteDocRef, voteObj);
t.update(recipeDocRef, { score: (currentRecipeScore + value) });
} else {
const voteData = voteDoc.data();
if ( voteData.value == value ) {
// existing vote is the same as the button that was pressed, so delete
// the vote document and revert the vote from the recipe's score
t.delete(voteDocRef);
t.update(recipeDocRef, { score: (currentRecipeScore - value) });
} else {
// existing vote is the opposite of the one pressed, so update the
// vote doc, then apply it to the recipe's score by doubling it.
// For example, if the current score is 1 and the user reverses their
// +1 vote by pressing -1, we apply -2 so the score will become -1.
t.set(voteDocRef, voteObj);
t.update(recipeDocRef, { score: (currentRecipeScore + (value*2))});
}
}
return Promise.resolve(true);
});
}
According to Firebase developer Nicolas Garnier, "What you are experiencing here is how Transactions work in Firestore: one of the transactions failed to write because the data has changed in the mean time, in this case Firestore re-runs the transaction again, until it succeeds. In the case of multiple Reviews being written at the same time some of them might need to be ran again after the first transaction because the data has changed. This is expected behavior and these errors should be taken more as warnings."
In other words, this is a normal result of the transaction retrying.
I used RxJS throttleTime to prevent the user from flooding the Firestore server with transactions by clicking the upvote/downvote buttons in rapid succession, and that greatly reduced the occurrences of this 400 error. In my app, there's no legitimate reason someone would need to clip upvote/downvote dozens of times per seconds. It's not a video game.

Purge data from redis cache in chunk

I need to delete a pool from redis cache. However, this pool might have millions of keys. I am using following code to delete the keys from cache
String regex = "*." + poolname + ".*";
Set<String> rkeys = jedis.keys(regex);
for (String key : rkeys) {
LOGGER.info("key ===>" + key);
jedis.del(key);
}
I am afraid that redis server might crash in case, there are million rows.
Is there any way I can tell redis to select only 100 rows and delete at time. Something like
while (true) {
//sleep for 1 minute
//get 100 rows from cache
if (keys.isEmpty()) {
break;
}
jedis.del(key);
}
Redis shouldn't ever crash, and I would test the scenario before making my code more complicated on a hunch. I just created a million keys and deleted them. It took 2 minutes and the bottleneck was the ruby client, not redid.
That said, you may want to check out https://redis.io/commands/unlink, which is a new non-blocking version of DEL.

How to decide who is the first player when user plays quick game?

I am using following code in onRoomConnected(int statusCode, Room room) for deciding who is the first player. But some times I am getting first/second for both players same. How to resolve this error.
if (quickGame) {
myTurn = room.getParticipants().get(0).getParticipantId().equals(myId);
} else {
myTurn = room.getCreatorId().equals(myId);
}
if (myTurn) {
Log.e(TAG, "First Player");
status.setText("Click a button to start");
} else {
Log.e(TAG, "Second Player");
status.setText("Wait for opponent to start");
}
The set of participant IDs is guaranteed to be the same to everybody who is in the room (but not across different matches). However, their order in the list is not guaranteed. So if you want to make an easy election (e.g. establish who goes first, etc), you must rely on the set of participant IDs, but not in the order. Some of the ways you can accomplish this are:
The participant ID that comes alphabetically first is the first player to play
The participant ID that comes alphabetically first is responsible for randomly electing a player to start first. The other clients will wait until that participants sends a reliable real time message containing the ID of the elected participant.
Method (2) is preferred, because it doesn't contain a possible bias.
Why? Although we don't specify what's the structure of a participant ID (it's just a string), the truth is that it does encode information, so if you use the participant ID as a rule, you might end up with a weird distribution of who goes first. For example, you might find that a particular player is always going first, but that's because, coincidentally, their participant ID is generated in such a way that this always happens. So it's definitely a better idea to use the participant ID to elect who is the authority to randomly decide who goes first, not who actually goes first.
One way to approach is to track the participantIDs, as they are generated on a per room basis. This is how I do it in my Android Code
#Override
public ArrayList<String> getActiveRoomPlayerIDs() {
if(mRoomCurrent != null) {
ArrayList<String> newList = new ArrayList<String>();
for (Participant p : mRoomCurrent.getParticipants()) {
dLog(listIgnoreTheseIDs.toString() + " is the list to ignore");
if(mRoomCurrent.getParticipantStatus(p.getParticipantId()) == Participant.STATUS_LEFT) {
dLog(p.getParticipantId() + " left the room");
} else {
newList.add(p.getParticipantId());
}
}
return newList;
}
return null;
}
The reason I approach like this, is, in case the room participants change during the game I can use this same approach to handle their leaving the room.
onRoomConnected is called for ALL opponents with the SAME number of participants, there is no varying number of how many are in that call
Added here for the edit.. in my libGDX side I then do this
private ArrayList<String> SortThisList(ArrayList<String> currentRoomIds) {
Collections.sort(currentRoomIds);
return currentRoomIds;
}
Then I use the sorted list to determine player order...
If there is no other criteria that matters you can use my technique. Simply pick the alphabetically smallest participant id as server after room formation is complete.
/**checks is this user is the alphabetically smallest participant id.
* if so then the user is server.
* #return if this user should be the server.
*/
private boolean isServer()
{
for(Participant p : mParticipants )
{
if(p.getParticipantId().compareTo(mMyId)<0)
return false;
}
return true;
}
I would suggest the following method:
When device A gets response from Google that room is connected, check if any other participants are present. If none are present assign device A as player 1.
When device B gets response from Google, it will find that there is another participant other than itself. In this case wait.
In device A, you will get a notification that participant has connected, start the game now and send appropriate message to device B.

Resources