学 赵 1 year ago
parent
commit
d5b0872cca
  1. 6
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/models/job-item.js
  2. 23
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/base-data/job-item.js
  3. 42
      code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/BQ/JobHostdService.cs
  4. 22
      code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/BQ/VmiAppService.cs
  5. 1
      code/src/Modules/SettleAccount/src/SettleAccount.Domain/Entities/BQ/Vmi/JobItem.cs
  6. 5051
      code/src/Modules/SettleAccount/src/SettleAccount.EntityFrameworkCore/Migrations/20230807063408_vmi10.Designer.cs
  7. 38
      code/src/Modules/SettleAccount/src/SettleAccount.EntityFrameworkCore/Migrations/20230807063408_vmi10.cs

6
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/models/job-item.js

@ -23,6 +23,12 @@ const schema = {
type: "boolean",
readOnly: true,
},
heartBeat: {
title: "心跳",
type: "string",
input: "datetime",
readOnly: true,
},
},
};

23
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/base-data/job-item.js

@ -1,31 +1,24 @@
import AppList from "../../components/list/index.js";
import html from "html";
import useConfig from "../../models/job-item.js";
import { ref, nextTick, onMounted, onUnmounted } from "vue";
import { ref, onMounted, onUnmounted } from "vue";
import useConfig2 from "../../models/job-log.js";
export default {
components: { AppList },
template: html`<app-list v-if="refresh" :config="config" @command="onCommand" />`,
template: html`<app-list ref="appListRef" :config="config" @command="onCommand" />`,
setup() {
const config = useConfig();
const onCommand = async (item, rows, load, showList) => {
console.log(item.path, item, rows);
console.log(showList);
const config = useConfig2();
config.query.schema.properties.filters.default[0].value = rows[0].id;
showList({ test: "test" }, "/base-data/job-log", config);
};
const refresh = ref(true);
onMounted(async () => {
PubSub.subscribe("JobItem", () => {
refresh.value = false;
nextTick(() => (refresh.value = true));
});
});
onUnmounted(() => {
PubSub.unsubscribe(onMonitor);
});
return { config, onCommand, refresh };
//
const appListRef = ref(null);
const event = "JobItem";
onMounted(() => PubSub.subscribe(event, async () => await appListRef.value.load()));
onUnmounted(() => PubSub.unsubscribe(event));
return { config, onCommand, appListRef };
},
};

42
code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/BQ/JobHostdService.cs

@ -85,14 +85,20 @@ public class JobHostdService : BackgroundService, IApplicationService
{
var jobItem = this.GetJobItem(job.Id);
Guid? jobLogId = null;
if (jobItem.IsRunning && (DateTime.Now - jobItem.HeartBeat.Value).TotalSeconds > 20)
{
JobItemStop(jobItem.Id);
}
if (!jobItem.IsRunning)
{
jobLogId = this.JobItemStart(job.Id);
scope.ServiceProvider.GetRequiredService<IHubContext<PageHub>>().Clients.All.ServerToClient("JobItem", "refresh", "");
using var timer = new System.Timers.Timer(10000);
if (jobLogId.HasValue)
{
try
{
timer.Elapsed += (s, e) => JobItemHeartBeat(job.Id);
scope.ServiceProvider.GetRequiredService<IHubContext<PageHub>>().Clients.All.ServerToClient("JobItem", "refresh", "");
await jobService.Invoke(scope.ServiceProvider).ConfigureAwait(false);
this.JobItemSuccess(job.Id, jobLogId.Value);
Debug.WriteLine($"{job.Name} 定时任务执行成功");
@ -103,7 +109,11 @@ public class JobHostdService : BackgroundService, IApplicationService
Console.WriteLine(ex.ToString());
this.JobItemFaild(job.Id, jobLogId.Value, ex);
}
scope.ServiceProvider.GetRequiredService<IHubContext<PageHub>>().Clients.All.ServerToClient("JobItem", "refresh", "");
finally
{
timer.Stop();
scope.ServiceProvider.GetRequiredService<IHubContext<PageHub>>().Clients.All.ServerToClient("JobItem", "refresh", "");
}
}
}
}
@ -173,6 +183,21 @@ public class JobHostdService : BackgroundService, IApplicationService
}
}
private void JobItemStop(Guid id)
{
using var scope = this._serviceProvider.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<SettleAccountDbContext>();
var entity = db.Set<JobItem>().FirstOrDefault(o => o.Id == id);
if (entity != null)
{
entity.IsRunning = false;
var log = db.Set<JobLog>().Where(o => o.JobId == id && o.End == null).OrderByDescending(o => o.Start).FirstOrDefault();
log.Success = false;
log.Exception = "心跳超时,自动停止";
db.SaveChanges();
}
}
private Guid? JobItemStart(Guid id)
{
using var scope = this._serviceProvider.CreateScope();
@ -181,6 +206,7 @@ public class JobHostdService : BackgroundService, IApplicationService
if (entity != null)
{
entity.IsRunning = true;
entity.HeartBeat = DateTime.Now;
var log = db.Set<JobLog>().Add(new JobLog { Start = DateTime.Now, JobId = entity.Id, Host = Dns.GetHostName() });
db.SaveChanges();
return log.Entity.Id;
@ -194,6 +220,18 @@ public class JobHostdService : BackgroundService, IApplicationService
return scope.ServiceProvider.GetRequiredService<SettleAccountDbContext>().Set<JobItem>().AsNoTracking().FirstOrDefault(o => o.Id == id);
}
private void JobItemHeartBeat(Guid id)
{
using var scope = this._serviceProvider.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<SettleAccountDbContext>();
var entity = db.Set<JobItem>().FirstOrDefault(o => o.Id == id);
if (entity != null)
{
entity.HeartBeat = DateTime.Now;
db.SaveChanges();
}
}
public void RemoveJob(JobItem item)
{
lock (_lockObj)

22
code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/BQ/VmiAppService.cs

@ -208,7 +208,18 @@ public class VmiAppService : ApplicationService, IVmiService, IJobService, ITran
var qty = balance.Qty + data.Qty;
balance.InjectFrom(data);
balance.Qty = qty;
this._balanceRepository.UpdateAsync(balance).Wait();
if (balance.Qty == decimal.Zero)
{
await this._balanceRepository.DeleteAsync(balance).ConfigureAwait(false);
}
else
{
await this._balanceRepository.UpdateAsync(balance).ConfigureAwait(false);
}
if (logType == VmiLogType.Type100 && balance.Qty < decimal.Zero && data.Qty > 0)
{
log.IsReplenished = true;
}
}
await _logRepository.InsertAsync(log).ConfigureAwait(false);
}
@ -253,7 +264,14 @@ public class VmiAppService : ApplicationService, IVmiService, IJobService, ITran
{
var qty = balance.Qty - data.Qty;
balance.Qty = qty;
this._balanceRepository.UpdateAsync(balance).Wait();
if (balance.Qty == decimal.Zero)
{
await this._balanceRepository.DeleteAsync(balance).ConfigureAwait(false);
}
else
{
await this._balanceRepository.UpdateAsync(balance).ConfigureAwait(false);
}
}
await _logRepository.InsertAsync(log).ConfigureAwait(false);
}

1
code/src/Modules/SettleAccount/src/SettleAccount.Domain/Entities/BQ/Vmi/JobItem.cs

@ -23,6 +23,7 @@ public class JobItem : Entity<Guid>
public string Service { get; set; }
public bool IsRunning { get; set; }
public DateTime? HeartBeat { get; set; }
[Timestamp]
public string ConcurrencyStamp { get; set; }

5051
code/src/Modules/SettleAccount/src/SettleAccount.EntityFrameworkCore/Migrations/20230807063408_vmi10.Designer.cs

File diff suppressed because it is too large

38
code/src/Modules/SettleAccount/src/SettleAccount.EntityFrameworkCore/Migrations/20230807063408_vmi10.cs

@ -0,0 +1,38 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Win.Sfs.SettleAccount.Migrations
{
public partial class vmi10 : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<DateTime>(
name: "HeartBeat",
table: "Set_JobItem",
type: "datetime2",
nullable: true);
migrationBuilder.UpdateData(
table: "Set_VmiBalance",
keyColumn: "Id",
keyValue: new Guid("ea936b34-ecd0-7dbd-85a9-57cd8b730873"),
column: "ConcurrencyStamp",
value: "2cc9803a5a8e420b80134104653ecde0");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "HeartBeat",
table: "Set_JobItem");
migrationBuilder.UpdateData(
table: "Set_VmiBalance",
keyColumn: "Id",
keyValue: new Guid("ea936b34-ecd0-7dbd-85a9-57cd8b730873"),
column: "ConcurrencyStamp",
value: "887ca64c266c48ac82dca90534f64225");
}
}
}
Loading…
Cancel
Save