I want to implement a function to migrate a user from one tenant to another.
I know this could be achieved simply by change user's tenant id.
The problem is, I have an order has this user id and tenant id recorded, if I simply updated this user's tenant id, i won't be able to locate the user using the data recorded in the order.
If I have to update all the orders during migrating process, this could take up a long time for a large database.
Since the default PK type for ABP is long, is it possible to replace it as guid or are there any options I could choose?
Thanks.
Related
I am building the inventory service, all tables keep track the owner of each record in column createdBy which store the user id.
The problem is this service does not hold the user info, so it cannot map the id to username which is required for FE to display data.
Calling user service to map the username and userid for each request does not make sense in term of decouple and performance. Because 1 request can ask for maximum 100 records. If I store the username instead of ID, there will be problem when user change their username.
Is there any better way or pattern to solve this problem?
I'd extend the info with the data needed with from the user service.
User name is a slow changing dimension so for most of the time the data is correct (i.e. "safe to cache")
Now we get to what to do when user info changes - this is, of course, a business decision. In some places it makes sense to keep the original info (for example what happens when the user is deleted - do we still want to keep the original user name (and whatever other info) that created the item). If this is not the case, you can use several strategies - you can have a daily (or whatever period) job to go and refresh the users info from the user service for all users used in the inventory, you can publish a daily summary of changes from the user service and have the inventory subscribe to that, you can publish changes as they happen and subscribe to that etc. - depending on the requirement for freshness. The technology to use depends on the strategy..
In my option what you have done so far is correct. Inventory related data should be Inventory Services' responsibility just like user related data should be User Services'.
It is FE's responsibility to fetch the relevant user details from User Service that are required to populate the UI (Remember, call backend for each user is not acceptable at all. Bulk search is more suitable).
What you can do is when you fetch inventory data from Inventory Service, you can publish a message to User Service to notify that "inventory related data was fetched for these users. So there is a possibility to fetch user related data for these users. Therefore you better cache them."
PS - I'm not an expert in microservices architecture. Please add any counter arguments if you have any.*
Can I register same user (login/e-mail) in more than on tenant, so an UserId can belong to multiple Tenants?
I ask that because instead of input Tenant on login, How hard is to achieve this approach below?
When user logs in, if they belong to multiple tenants, boilerplate will identify this and show the user a select dropdown to choose which tenant they want to manage.
I feel this approach is more professional than input a tenant string value on login page.
it's not possible in aspnetboilerplate structure. a user must belong to only a single tenant.
I wanna code a telegram bot, so when I gonna receive messages from a user I should know about last message he/she sent to me and in which step does he/she located. So I should store sessions of the user (I understood this when I searched) but I don't know what exactly should I do?
I know I need a table in a db that stores UserId, ChatId but I don't know these:
How to make a root for steps and store them in db (I mean how do I understand where the user is located now)
What are other columns that I need to store as a session?
How many messages should I store in the database? And do I need one row for each message?
If you just have to store session in your database you don't need to store messages. Maybe you could want to store also messages but it's not necessarily related.
Let's assume you have a "preferences" menu in your bot where the user can write his input. You ask for the name, age, gender etc.
How do your know when the user writes the input of it's about the name or the gender etc?
You save sessions in your db. When the bot receives the message you check in what session the user is in to run the right function.
An easy solution could be a sql database.
The primary key column is the telegram user ID ( you additionally can add a chat id column if it's intended to work both in private and group chats) and a "session" column TEXT where you log user steps. The session column can be NULL by default. If the bot expects the gender (because the user issued /gender command) you can update the column "session" with the word "gender" so when the message arrives you know how to handle it checking the gender column of that user id and as soon as you runned the right function, you update to NULL again the column "session".
you can create a db with these columns.
UserID, ChatID, State, Name, Age, Gender ...
on each incoming update you will check if user exists on you db then check the user's State and respond appropriately and update the state at the end.
What might be a good way to introduce BIGINT into the ASP.NET Membership functionality to reference users uniquely and to use that BIGINT field as a tenant_id? It would be perfect to keep the existing functionality generating UserIds in the form of GUIDs and not to implement a membership provider from ground zero. Since application will be running on multiple servers, the BIGINT tenant_id must be unique and it should not depend on some central authority generating these IDs. It will be easy to use these tenant_id with a SPLIT AT command down the road which will allow bucketing users into new federated members. Any thoughts on this?
Thanks
You can use bigint. But you may have to modify all stored procedures that rely on user ID. Making ID global unique is usually not a problem. As long as the ID is the primary key, database will force it to be unique. Otherwise you will get errors when inserting new data (in that case, you can modify ID and retry).
So the most important difference is you may need to modify stored procedures. You have a choice here. If you use GUID, you don't need to do anything. But it may be difficult to predict how to split the federation to balance queries. As pointed out in another thread (http://stackoverflow.com/questions/10885768/sql-azure-split-on-uniqueidentifier-guid/10890552#comment14211028_10890552), you can sort existing data at the mid point. But you don't know future data will be inserted in which federation. There's a potential risk that federations will become unbalanced, and you may need to merge and split them at a regular interval to keep them in shape.
By using bigint, you have better control over the key. For example, you have two federations. The first has ID from 1 to 10000, and the second has ID from 10001 to 20000. When creating a new user, you first check how many records are in each federation. Suppose federation 1 has 500 records and federation 2 has 1000 records, to balance the load, you choose to insert to federation 1, so you choose an ID between 1 and 10000. But using bigint, you may need to do more work to modify stored procedures.
I am assuming I cannot do this using sessions but rather the DATABASE. So the user would sign in, it would set their TIMESTAMP and I display that from the database. Then it becomes deleted when the user logs out or their session is terminated. How would the code look for this?
The better question is, is my logic correct? Would this work? Does this make sense?
By default application servers store session data in temporary files on the server.
By storing session data in a database table you are able to create an interface that will show information about the users that are logged in. Apart from that, using this (database) approach is a serious advantage if you need to scale your application by adding more than one server.
One of the most popular ways to implement such a functionality is to create a session table containing your users' session data. This may look like:
create table session (
id number primary key,
data varchar(240),
timestamp date
);
The data column stores all the session data in a serialized form this is deserialized each time a user requests the data.
Serialization and deserialization may have inbuilt support depending on the platform you are using. For example, if you are using PHP, the functions session_encode and session_decode may be found useful.
You can't find out when a user logs out in PHP and the Javascript workarounds are a bit far from a stable solution.
A couple of things you need to do: Create a column in your user table called last_activity and update their last_activity to the current time whenever a user loads a page.
For a list of who's online, query the db for users with last_activity values more recent than 10 or 20 or whatever minutes ago.
To update the last_activity column use:
UPDATE users SET last_activity=CURRENT_TIMESTAMP() WHERE id=2
For a list of users online
SELECT * FROM users where last_activity >= (CURRENT_TIMESTAMP()-(60*20))