Commit bf4d5769 by pye52

1、增加日志文件及数据库清理监测

2、现在在线支付超时改为10秒
3、更新文档
parent 6257d72d
......@@ -7,8 +7,8 @@ android {
applicationId "com.bgycc.smartcanteen"
minSdkVersion 22
targetSdkVersion 29
versionCode 13
versionName "1.3.3"
versionCode 14
versionName "1.3.4"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
ndk {
abiFilters "armeabi", "armeabi-v7a", "x86", "mips"
......
......@@ -16,6 +16,8 @@ import java.io.File;
public class RootApp extends Application implements Configuration.Provider {
private static final String LOG_PREFIX = "app";
private static final String LOG_DIR = "log";
// 日志文件保留周期
private static final int LOG_SAVE_DAYS = 7;
@Override
public void onCreate() {
......@@ -27,7 +29,8 @@ public class RootApp extends Application implements Configuration.Provider {
.setDir(logDir)
.setLog2FileSwitch(true)
.setBorderSwitch(false)
.setFilePrefix(LOG_PREFIX);
.setFilePrefix(LOG_PREFIX)
.setSaveDays(LOG_SAVE_DAYS);
}
@NonNull
......
......@@ -271,6 +271,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
handler.post(updateTimeRunnable);
WorkerUtils.startLogFilesMonitor(this);
WorkerUtils.startDatabaseMonitor(this);
SCWebSocketClient.getInstance().tryConnect();
}
......@@ -334,6 +335,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
TTSHelper.release();
SCWebSocketClient.getInstance().realClose();
SCTaskExecutor.getInstance().quit();
WorkerUtils.stopDatabaseMonitor(this);
WorkerUtils.stopLogFilesMonitor(this);
}
......
......@@ -11,6 +11,7 @@ import androidx.room.DatabaseConfiguration;
import androidx.room.InvalidationTracker;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import androidx.room.migration.Migration;
import androidx.sqlite.db.SupportSQLiteDatabase;
import androidx.sqlite.db.SupportSQLiteOpenHelper;
......@@ -34,7 +35,7 @@ import java.util.List;
PayData.class,
PayResponse.class
},
version = 1,
version = 2,
exportSchema = false)
public abstract class DatabaseManager extends RoomDatabase {
private static final String TAG = "SmartCanteen_Database";
......@@ -85,6 +86,7 @@ public abstract class DatabaseManager extends RoomDatabase {
forceToPayOffline(db, list);
}
})
.addMigrations(new _1To_2Migration())
// 一旦版本不兼容则清空数据库
.fallbackToDestructiveMigration()
.allowMainThreadQueries()
......
......@@ -22,4 +22,12 @@ public interface CommandDao {
@Update(onConflict = OnConflictStrategy.REPLACE)
int updateCommand(Command command);
@Query("select count(*) from command")
int countOldData();
// 删除执行完毕的指令
@Query("delete from command where id in " +
"(select id from command order by id asc limit :limit)")
int clearOldData(int limit);
}
......@@ -13,10 +13,12 @@ import java.util.List;
@Dao
public interface PayDataDao {
/**
* 获取所有需要离线支付的订单
* 获取需要离线支付的订单(同时1h内未上传过的)
*/
@Query("select * from paydata where payState == -1")
List<PayData> queryPayOfflineData();
@Query("select * from paydata " +
"where payState == -1 and (:currentTim - uploadTime) > (1 * 60 * 60 * 1000) " +
"limit :limit")
List<PayData> queryPayOfflineData(long currentTim, int limit);
/**
* 根据支付码获取指定订单
......@@ -32,4 +34,12 @@ public interface PayDataDao {
@Update(onConflict = OnConflictStrategy.REPLACE)
int updatePayData(List<PayData> data);
@Query("select count(*) from paydata where payState == 1 or payState == -2")
int countOldData();
// 删除"支付成功"和"支付失败"的旧订单
@Query("delete from paydata where payCode in " +
"(select payCode from paydata where payState == 1 or payState == -2 order by time asc limit :limit)")
int clearOldData(int limit);
}
......@@ -3,6 +3,7 @@ package com.bgycc.smartcanteen.data.dao;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import com.bgycc.smartcanteen.entity.PayResponse;
......@@ -10,4 +11,12 @@ import com.bgycc.smartcanteen.entity.PayResponse;
public interface PayResponseDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
long insertPayResponse(PayResponse response);
@Query("select count(*) from payresponse")
int countOldData();
// 删除旧的服务器通知
@Query("delete from payresponse where id in " +
"(select id from payresponse order by id asc limit :limit)")
int clearOldData(int limit);
}
......@@ -28,6 +28,8 @@ public class PayData {
private String payCode = "";
private String terminalType;
private long time;
// 记录订单发到后台的时间
private long uploadTime;
/**
* 1 -> 支付成功(在线支付/离线支付成功后标记)
* 0 -> 在线支付(任务创建时默认标记)
......@@ -46,6 +48,7 @@ public class PayData {
this.terminalType = terminalType;
this.time = System.currentTimeMillis() / 1000;
this.payState = PAY_ONLINE;
this.uploadTime = 0;
}
public boolean success() {
......@@ -112,6 +115,14 @@ public class PayData {
this.time = time;
}
public long getUploadTime() {
return uploadTime;
}
public void setUploadTime(long uploadTime) {
this.uploadTime = uploadTime;
}
public int getPayState() {
return payState;
}
......@@ -124,17 +135,18 @@ public class PayData {
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PayData data = (PayData) o;
return time == data.time &&
payState == data.payState &&
Objects.equals(equipmentNo, data.equipmentNo) &&
Objects.equals(payCode, data.payCode) &&
Objects.equals(terminalType, data.terminalType);
PayData payData = (PayData) o;
return time == payData.time &&
uploadTime == payData.uploadTime &&
payState == payData.payState &&
Objects.equals(equipmentNo, payData.equipmentNo) &&
payCode.equals(payData.payCode) &&
Objects.equals(terminalType, payData.terminalType);
}
@Override
public int hashCode() {
return Objects.hash(equipmentNo, payCode, terminalType, time, payState);
return Objects.hash(equipmentNo, payCode, terminalType, time, uploadTime, payState);
}
@Override
......@@ -144,6 +156,7 @@ public class PayData {
", payCode='" + payCode + '\'' +
", terminalType='" + terminalType + '\'' +
", time=" + time +
", uploadTime=" + uploadTime +
", payState=" + payState +
'}';
}
......
......@@ -25,4 +25,12 @@ public class CommandRepository {
public int updateCommand(Command command) {
return dao.updateCommand(command);
}
public int countOldData() {
return dao.countOldData();
}
public int clearOldData(int limit) {
return dao.clearOldData(limit);
}
}
......@@ -12,8 +12,8 @@ public class PayDataRepository {
this.dao = dao;
}
public List<PayData> queryPayOfflineData() {
return dao.queryPayOfflineData();
public List<PayData> queryPayOfflineData(long currentTime, int limit) {
return dao.queryPayOfflineData(currentTime, limit);
}
public PayData queryPayDataByPayCode(String payCode) {
......@@ -31,4 +31,12 @@ public class PayDataRepository {
public int updatePayData(PayData data) {
return dao.updatePayData(data);
}
public int countOldData() {
return dao.countOldData();
}
public int clearOldData(int limit) {
return dao.clearOldData(limit);
}
}
......@@ -13,4 +13,12 @@ public class PayResponseRepository {
public long insertPayResponse(PayResponse response) {
return dao.insertPayResponse(response);
}
public int countOldData() {
return dao.countOldData();
}
public int clearOldData(int limit) {
return dao.clearOldData(limit);
}
}
......@@ -5,16 +5,21 @@ import android.content.Context;
import androidx.work.PeriodicWorkRequest;
import androidx.work.WorkManager;
import com.bgycc.smartcanteen.worker.DatabaseMonitor;
import com.bgycc.smartcanteen.worker.LogFileMonitor;
import java.util.concurrent.TimeUnit;
public class WorkerUtils {
private static final String LOG_MONITOR_WORKER = "worker_log_monitor";
private static final String DATABASE_MONITOR_WORKER = "database_log_monitor";
private static final int LOG_REPEAT_INTERVAL = 4;
private static final int DATABASE_REPEAT_INTERVAL = 12;
// 每隔一定时间检查日志文件夹并进行清理
public static void startLogFilesMonitor(Context context) {
PeriodicWorkRequest request = new PeriodicWorkRequest.Builder(LogFileMonitor.class, 4, TimeUnit.HOURS)
PeriodicWorkRequest request = new PeriodicWorkRequest.Builder(LogFileMonitor.class, LOG_REPEAT_INTERVAL, TimeUnit.HOURS)
.addTag(LOG_MONITOR_WORKER)
.build();
WorkManager.getInstance(context)
......@@ -25,4 +30,18 @@ public class WorkerUtils {
WorkManager.getInstance(context)
.cancelAllWorkByTag(LOG_MONITOR_WORKER);
}
// 每隔一定时间检查数据库并进行清理
public static void startDatabaseMonitor(Context context) {
PeriodicWorkRequest request = new PeriodicWorkRequest.Builder(DatabaseMonitor.class, DATABASE_REPEAT_INTERVAL, TimeUnit.HOURS)
.addTag(DATABASE_MONITOR_WORKER)
.build();
WorkManager.getInstance(context)
.enqueue(request);
}
public static void stopDatabaseMonitor(Context context) {
WorkManager.getInstance(context)
.cancelAllWorkByTag(DATABASE_MONITOR_WORKER);
}
}
......@@ -37,7 +37,7 @@ import static com.bgycc.smartcanteen.utils.SmartCanteenUtils.TAG;
* 支付状态(空闲、发送订单信息、支付中、支付成功、支付失败)都会通过{@link PayOnlineState}发出通知 <br/><br/>
*/
public class PayOnlineViewModel extends ViewModel {
private static final long TIMEOUT = 5 * 1000;
private static final long TIMEOUT = 10 * 1000;
// 在线支付延迟150ms执行,留出时间给扫码反馈
private static final long REQUEST_DELAY = 150;
private static final long DEFAULT_DELAY = 3 * 1000;
......
package com.bgycc.smartcanteen.worker;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.work.Worker;
import androidx.work.WorkerParameters;
import com.bgycc.smartcanteen.Injection;
import com.bgycc.smartcanteen.repository.CommandRepository;
import com.bgycc.smartcanteen.repository.PayDataRepository;
import com.bgycc.smartcanteen.repository.PayResponseRepository;
import com.blankj.utilcode.util.LogUtils;
import static com.bgycc.smartcanteen.utils.SmartCanteenUtils.TAG;
public class DatabaseMonitor extends Worker {
private CommandRepository commandRepository;
private PayDataRepository payDataRepository;
private PayResponseRepository payResponseRepository;
// 数据清理阈值
private static final int DATABASE_LIMIT = 50 * 10000;
public DatabaseMonitor(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
commandRepository = Injection.provideCommandRepositorySingleton();
payDataRepository = Injection.providePayDataRepositorySingleton();
payResponseRepository = Injection.providePayResponseRepositorySingleton();
}
@NonNull
@Override
public Result doWork() {
StringBuilder builder = new StringBuilder("清理阈值: " + DATABASE_LIMIT);
int commandCount = commandRepository.countOldData();
builder.append("\n")
.append("command数据库当前旧数据量: ")
.append(commandCount);
if (commandCount >= DATABASE_LIMIT) {
commandRepository.clearOldData(DATABASE_LIMIT);
builder.append("\n")
.append("command数据库已清理旧数据");
}
int payDataCount = payDataRepository.countOldData();
builder.append("\n")
.append("payData数据库当前旧数据量: ")
.append(payDataCount);
if (payDataCount >= DATABASE_LIMIT) {
payDataRepository.clearOldData(DATABASE_LIMIT);
builder.append("\n")
.append("payData数据库已清理旧数据");
}
int payResponseCount = payResponseRepository.countOldData();
builder.append("\n")
.append("payResponse数据库当前旧数据量: ")
.append(payResponseCount);
if (payResponseCount >= DATABASE_LIMIT) {
payResponseRepository.clearOldData(DATABASE_LIMIT);
builder.append("\n")
.append("payResponse数据库已清理旧数据");
}
LogUtils.d(TAG, builder);
return Result.success();
}
}
......@@ -31,17 +31,28 @@ public class LogFileMonitor extends Worker {
while (availableSize < (totalSize * 0.1f)) {
// 当可用小于10%时,删除旧日志文件
List<File> logFiles = LogUtils.getLogFiles();
Collections.sort(logFiles, (f1, f2) -> {
if (f1.lastModified() == f2.lastModified()) {
return 0;
if (logFiles.isEmpty()) {
LogUtils.w(TAG, "没有日志文件,但内存空间已满");
return Result.success();
}
if (logFiles.size() == 1) {
// 只有一个日志文件时,直接删除
FileUtils.delete(logFiles.get(0));
return Result.success();
} else {
// 有多个文件时,先排序,后删除最旧的两份日志
Collections.sort(logFiles, (f1, f2) -> {
if (f1.lastModified() == f2.lastModified()) {
return 0;
}
return (f1.lastModified() > f2.lastModified()) ? 1 : -1;
});
for (File f : logFiles.subList(0, 2)) {
FileUtils.delete(f);
}
return (f1.lastModified() > f2.lastModified()) ? 1 : -1;
});
for (File f : logFiles.subList(0, 2)) {
FileUtils.delete(f);
totalSize = FileUtils.getFsTotalSize(logDirPath);
availableSize = FileUtils.getFsAvailableSize(logDirPath);
}
totalSize = FileUtils.getFsTotalSize(logDirPath);
availableSize = FileUtils.getFsAvailableSize(logDirPath);
}
return Result.success();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment