moqui / moqui-framework

Use Moqui Framework to build enterprise applications based on Java. It includes tools for databases (relational, graph, document), local and web services, web and other UI with screens and forms, security, file/resource access, scripts, templates, l10n, caching, logging, search, rules, workflow, multi-instance, and integration.
http://www.moqui.org
Other
279 stars 199 forks source link

getLoginKey Need to optimize #598

Open daiagou opened 1 year ago

daiagou commented 1 year ago

Refer to the code for getLoginKey, as follows:

 @Override String getLoginKey(float expireHours) {
        String userId = getUserId()
        if (!userId) throw new AuthenticationRequiredException("No active user, cannot get login key")

        // generate login key
        String loginKey = StringUtilities.getRandomString(40)

        // save hashed in UserLoginKey, calc expire and set from/thru dates
        String hashedKey = eci.ecfi.getSimpleHash(loginKey, "", eci.ecfi.getLoginKeyHashType(), false)
        Timestamp fromDate = getNowTimestamp()
        long thruTime = fromDate.getTime() + Math.round(expireHours * 60*60*1000)
        eci.serviceFacade.sync().name("create", "moqui.security.UserLoginKey")
                .parameters([loginKey:hashedKey, userId:userId, fromDate:fromDate, thruDate:new Timestamp(thruTime)])
                .disableAuthz().requireNewTransaction(true).call()

        // clean out expired keys
        eci.entity.find("moqui.security.UserLoginKey").condition("userId", userId)
                .condition("thruDate", EntityCondition.LESS_THAN, fromDate).disableAuthz().deleteAll()

        return loginKey
    }

The deleteAll() operation is not a batch deletion. Instead, delete one by one in the for loop. If there is a lot of user login information, it can greatly affect performance. For example, in our current scenario, we use an anonymous user to access some interfaces that do not require login before the user logs in, such as the homepage product list. So every day, the login information of this anonymous user can reach several hundred thousand. Once it expires and needs to be deleted, tens of thousands of entries may need to be deleted at once, and then multiple users will come and delete it at the same time. This login interface will time out due to slow deletion.

There are two optimization suggestions:

  1. Do not delete in a loop, but delete in batches based on time. For example: DELETE from user Login Key where USER ID=? And THRU DATE<?
  2. It can be deleted asynchronously, and even use jobs to fix a certain point in the evening when users are not using them.