Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lazy wait details finished #678

Merged
merged 5 commits into from
Nov 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion @rbv
Submodule @rbv updated from 12e3c9 to 416bec
Original file line number Diff line number Diff line change
Expand Up @@ -126,30 +126,44 @@ public Record createOrUpdate(Record record) {
// 含明细
final boolean hasDetails = details != null && !details.isEmpty();

boolean lazyAutoApprovalForDetails = false;
boolean lazyAutoTransformForDetails = false;
// 延迟执行触发器,因为明细尚未保存好
boolean lazyAutoApproval4Details = false;
boolean lazyAutoTransform4Details = false;
boolean lazyHookUrl4Details = false;
if (hasDetails) {
// fix: v3.2.2

// 自动审批 fix: v3.2.2

TriggerAction[] hasAutoApprovalTriggers = getSpecTriggers(
record.getEntity(), ActionType.AUTOAPPROVAL, TriggerWhen.CREATE, TriggerWhen.UPDATE);
lazyAutoApprovalForDetails = hasAutoApprovalTriggers.length > 0;
lazyAutoApproval4Details = hasAutoApprovalTriggers.length > 0;
// FIXME 此判断可能无意义,待进一步测试后确定是否保留
if (!lazyAutoApprovalForDetails) {
if (!lazyAutoApproval4Details) {
TriggerAction[] hasOnApprovedTriggers = getSpecTriggers(
record.getEntity().getDetailEntity(), null, TriggerWhen.APPROVED);
lazyAutoApprovalForDetails = hasOnApprovedTriggers.length > 0;
lazyAutoApproval4Details = hasOnApprovedTriggers.length > 0;
}
// 自动审批延迟执行,因为明细尚未保存好
if (lazyAutoApprovalForDetails) AutoApproval.setLazyAutoApproval();
if (lazyAutoApproval4Details) AutoApproval.setLazy();

// 自动转换

TriggerAction[] hasAutoTransformTriggers = getSpecTriggers(
record.getEntity(), ActionType.AUTOTRANSFORM, TriggerWhen.CREATE, TriggerWhen.UPDATE);
lazyAutoTransformForDetails = hasAutoTransformTriggers.length > 0;
lazyAutoTransform4Details = hasAutoTransformTriggers.length > 0;
// 记录转换延迟执行,因为明细尚未保存好
if (lazyAutoTransformForDetails) CommonsUtils.invokeMethod("com.rebuild.rbv.trigger.AutoTransform#setLazyAutoTransform");
if (lazyAutoTransform4Details) CommonsUtils.invokeMethod("com.rebuild.rbv.trigger.AutoTransform#setLazy");

// URL 回调 v3.5

TriggerAction[] hasHookUrlTriggers = getSpecTriggers(
record.getEntity(), ActionType.HOOKURL, TriggerWhen.CREATE, TriggerWhen.UPDATE, TriggerWhen.DELETE);
lazyHookUrl4Details = hasHookUrlTriggers.length > 0;
// 对于全量推送,明细尚未保存好
if (lazyHookUrl4Details) CommonsUtils.invokeMethod("com.rebuild.rbv.trigger.HookUrl#setLazy");
}

// 保证顺序
// 保证执行顺序
Map<Integer, ID> detaileds = new TreeMap<>();

try {
Expand Down Expand Up @@ -200,12 +214,9 @@ record = record.getPrimary() == null ? create(record) : update(record);
return record;

} finally {
if (lazyAutoApprovalForDetails) {
AutoApproval.executeLazyAutoApproval();
}
if (lazyAutoTransformForDetails) {
CommonsUtils.invokeMethod("com.rebuild.rbv.trigger.AutoTransform#executeLazyAutoTransform");
}
if (lazyAutoApproval4Details) AutoApproval.executeLazy();
if (lazyAutoTransform4Details) CommonsUtils.invokeMethod("com.rebuild.rbv.trigger.AutoTransform#executeLazy");
if (lazyHookUrl4Details) CommonsUtils.invokeMethod("com.rebuild.rbv.trigger.HookUrl#executeLazy");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,11 @@ public ID transform(ID sourceRecordId, ID specMainId) {
final boolean checkNullable = transConfig.getBooleanValue("checkNullable35");

Record main = transformRecord(sourceEntity, targetEntity, fieldsMapping, sourceRecordId, dvMap, false, false, checkNullable);
ID newId;
ID theNewId;

// v3.5 需要先回填
// 因为可能以回填字段作为条件进行转换一次判断
final boolean fillbackFix = fillback(sourceRecordId, EntityHelper.newUnsavedId(main.getEntity().getEntityCode()));

// 有多条(主+明细)
if (sourceDetails != null && sourceDetails.length > 0) {
Expand All @@ -155,15 +159,15 @@ public ID transform(ID sourceRecordId, ID specMainId) {
transformRecord(sourceDetailEntity, targetDetailEntity, fieldsMappingDetail, (ID) d[0], null, false, false, checkNullable));
}

newId = saveRecord(main, detailsList);
theNewId = saveRecord(main, detailsList);
} else {
newId = saveRecord(main, null);
theNewId = saveRecord(main, null);
}

// 回填
fillback(sourceRecordId, newId);
// 回填修正
if (fillbackFix) fillback(sourceRecordId, theNewId);

return newId;
return theNewId;
}

private ID saveRecord(Record record, List<Record> detailsList) {
Expand Down Expand Up @@ -204,15 +208,15 @@ protected boolean fillback(ID sourceRecordId, ID newId) {

// 此配置未开放
int fillbackMode = transConfig.getIntValue("fillbackMode");
if (fillbackMode == 2) {
if (fillbackMode == 2 && !EntityHelper.isUnsavedId(newId)) {
GeneralEntityServiceContextHolder.setAllowForceUpdate(updateSource.getPrimary());
try {
Application.getEntityService(sourceEntity.getEntityCode()).update(updateSource);
} finally {
GeneralEntityServiceContextHolder.isAllowForceUpdateOnce();
}
} else {
// FIXME 回填仅更新,无业务规则
// 无传播更新
Application.getCommonsService().update(updateSource, false);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*!
Copyright (c) REBUILD <https://getrebuild.com/> and/or its owners. All rights reserved.

rebuild is dual-licensed under commercial and open source licenses (GPLv3).
See LICENSE and COMMERCIAL in the project root for license information.
*/

package com.rebuild.core.service.trigger;

/**
* 部分触发器执行需要等到明细记录处理完成才能执行
*
* @author devezhao
* @since 2023/11/11
*/
public interface LazyWaitDetailsFinished {

String FLAG_LAZY = "lazy";

// setLazy
// isLazy
// executeLazy
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.rebuild.core.service.general.OperatingContext;
import com.rebuild.core.service.trigger.ActionContext;
import com.rebuild.core.service.trigger.ActionType;
import com.rebuild.core.service.trigger.LazyWaitDetailsFinished;
import com.rebuild.core.service.trigger.TriggerAction;
import com.rebuild.core.service.trigger.TriggerException;
import com.rebuild.core.service.trigger.TriggerResult;
Expand All @@ -37,10 +38,11 @@
* @since 2020/7/31
*/
@Slf4j
public class AutoApproval extends TriggerAction {
public class AutoApproval extends TriggerAction implements LazyWaitDetailsFinished {

// 延迟执行
private static final ThreadLocal<List<AutoApproval>> LAZY_AUTOAPPROVAL = new NamedThreadLocal<>("Lazy AutoApproval");
private OperatingContext operatingContext;
private OperatingContext keepOperatingContext;

public AutoApproval(ActionContext context) {
super(context);
Expand All @@ -58,19 +60,19 @@ public boolean isUsableSourceEntity(int entityCode) {

@Override
public Object execute(OperatingContext operatingContext) throws TriggerException {
this.operatingContext = operatingContext;
this.keepOperatingContext = operatingContext;
List<AutoApproval> lazyed;
if ((lazyed = isLazyAutoApproval(Boolean.FALSE)) != null) {
if ((lazyed = isLazy(false)) != null) {
lazyed.add(this);
log.info("Lazy AutoApproval : {}", lazyed);
return "lazy";
return FLAG_LAZY;
}

ID recordId = operatingContext.getFixedRecordId();
String useApproval = ((JSONObject) actionContext.getActionContent()).getString("useApproval");

// 优先使用当前用户
ID approver = ObjectUtils.defaultIfNull(UserContextHolder.getUser(Boolean.TRUE), UserService.SYSTEM_USER);
ID approver = ObjectUtils.defaultIfNull(UserContextHolder.getUser(true), UserService.SYSTEM_USER);
ID approvalId = ID.isId(useApproval) ? ID.valueOf(useApproval) : null;

// v2.10
Expand All @@ -89,24 +91,23 @@ public Object execute(OperatingContext operatingContext) throws TriggerException
@Override
public String toString() {
String s = super.toString();
if (operatingContext != null) s += "#OperatingContext:" + operatingContext;
if (keepOperatingContext != null) s += "#OperatingContext:" + keepOperatingContext;
return s;
}

// --

/**
* 跳过自动审批
* @see #isLazyAutoApproval(boolean)
*/
public static void setLazyAutoApproval() {
public static void setLazy() {
LAZY_AUTOAPPROVAL.set(new ArrayList<>());
}

/**
* @param once
* @return
*/
public static List<AutoApproval> isLazyAutoApproval(boolean once) {
public static List<AutoApproval> isLazy(boolean once) {
List<AutoApproval> lazyed = LAZY_AUTOAPPROVAL.get();
if (lazyed != null && once) LAZY_AUTOAPPROVAL.remove();
return lazyed;
Expand All @@ -115,12 +116,12 @@ public static List<AutoApproval> isLazyAutoApproval(boolean once) {
/**
* @return
*/
public static int executeLazyAutoApproval() {
List<AutoApproval> lazyed = isLazyAutoApproval(Boolean.TRUE);
public static int executeLazy() {
List<AutoApproval> lazyed = isLazy(true);
if (lazyed != null) {
for (AutoApproval a : lazyed) {
log.info("Lazy AutoApproval execute : {}", a);
Object res = a.execute(a.operatingContext);
Object res = a.execute(a.keepOperatingContext);

CommonsLog.createLog(TYPE_TRIGGER,
UserService.SYSTEM_USER, a.getActionContext().getConfigId(), res.toString());
Expand Down
17 changes: 13 additions & 4 deletions src/main/java/com/rebuild/utils/OkHttpUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,21 @@
import com.rebuild.core.Application;
import com.rebuild.core.support.RebuildConfiguration;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.SystemUtils;
import org.springframework.http.HttpHeaders;

import java.io.*;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.Locale;
Expand Down Expand Up @@ -56,8 +65,8 @@ synchronized public static OkHttpClient getHttpClient() {
if (okHttpClient == null) {
okHttpClient = new OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.retryOnConnectionFailure(true)
.hostnameVerifier((s, sslSession) -> true) // NOT SAFE!!!
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ public RespBody transform(HttpServletRequest request) {
}

try {
ID newId = transfomer.transform(sourceRecord, mainid);
return RespBody.ok(newId);
ID theNewId = transfomer.transform(sourceRecord, mainid);
return RespBody.ok(theNewId);
} catch (Exception ex) {
log.warn(">>>>> {}", ex.getLocalizedMessage());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ $(document).ready(() => {

const fillbackFields = []
wpc.sourceEntity.fields.forEach((item) => {
if (!item.name.includes('.') && item.type === 'REFERENCE' && item.ref[0] === wpc.targetEntity.entity) {
if (item.name.includes('.')) return
if ((item.type === 'REFERENCE' && item.ref[0] === wpc.targetEntity.entity) || item.type === 'ANYREFERENCE') {
fillbackFields.push({ id: item.name, text: item.label })
}
})
Expand Down
11 changes: 1 addition & 10 deletions src/main/resources/web/assets/js/bizuser/role-privileges.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,16 +165,7 @@ const loadRoles = function () {
extrasAction={(item) => {
return (
<RF>
<span
className="action"
onClick={() => {
RbFormModal.create({
title: $L('编辑角色'),
entity: 'Role',
icon: 'lock',
id: item.id,
})
}}>
<span className="action" onClick={() => RbFormModal.create({ title: $L('编辑角色'), entity: 'Role', icon: 'lock', id: item.id }, true)}>
<i className="zmdi zmdi-edit" />
</span>
<span
Expand Down
7 changes: 3 additions & 4 deletions src/main/resources/web/assets/js/rb-base.js
Original file line number Diff line number Diff line change
Expand Up @@ -390,12 +390,11 @@ var $random = function (prefix, alphabetic, maxLength) {
var $same = function (a, b) {
if (Object.is(a, b)) return true
if (a && b) {
if ($.type(a) === 'object' && $.type(b) === 'object') {
var aType = $.type(a)
var bType = $.type(b)
if ((aType === 'object' && bType === 'object') || (aType === 'array' && bType === 'array')) {
a = JSON.stringify(a)
b = JSON.stringify(b)
} else if ($.type(a) === 'array' && $.type(b) === 'array') {
a = a.join(',')
b = b.join(',')
}
}
if (a === b) return true
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/web/assets/js/rb-datalist.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const RbListPage = {
$('.J_edit').on('click', () => {
const ids = this._RbList.getSelectedIds()
if (ids.length >= 1) {
RbFormModal.create({ id: ids[0], title: $L('编辑%s', entity[1]), entity: entity[0], icon: entity[2] })
RbFormModal.create({ id: ids[0], title: $L('编辑%s', entity[1]), entity: entity[0], icon: entity[2] }, true)
}
})

Expand Down
17 changes: 2 additions & 15 deletions src/main/resources/web/assets/js/rb-forms.js
Original file line number Diff line number Diff line change
Expand Up @@ -708,12 +708,7 @@ class RbForm extends React.Component {
} else if (next === RbForm.NEXT_ADDDETAIL) {
const iv = $$$parent.props.initialValue
const dm = this.props.rawModel.entityMeta
RbFormModal.create({
title: $L('添加%s', dm.entityLabel),
entity: dm.entity,
icon: dm.icon,
initialValue: iv,
})
RbFormModal.create({ title: $L('添加%s', dm.entityLabel), entity: dm.entity, icon: dm.icon, initialValue: iv })
} else if (next === RbForm.NEXT_VIEW && window.RbViewModal) {
window.RbViewModal.create({ id: recordId, entity: this.state.entity })
if (window.RbListPage) {
Expand Down Expand Up @@ -2077,15 +2072,7 @@ class RbFormReference extends RbFormElement {

quickNew() {
const e = this.props.referenceEntity
RbFormModal.create(
{
title: $L('新建%s', e.entityLabel),
entity: e.entity,
icon: e.icon,
postAfter: (id) => this.showSearcher_call([id], this),
},
true
)
RbFormModal.create({ title: $L('新建%s', e.entityLabel), entity: e.entity, icon: e.icon, postAfter: (id) => this.showSearcher_call([id], this) }, true)
}
}

Expand Down
5 changes: 2 additions & 3 deletions src/main/resources/web/assets/js/rb-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ See LICENSE and COMMERCIAL in the project root for license information.
/* !!! KEEP IT ES5 COMPATIBLE !!! */

// GA
(function () {
;(function () {
const gaScript = document.createElement('script')
gaScript.src = 'https://www.googletagmanager.com/gtag/js?id=G-ZCZHJPMEG7'
gaScript.async = true
Expand Down Expand Up @@ -180,8 +180,7 @@ $(function () {
})
})

// __LAB
if (rb.env === 'dev' && window.sessionStorage) {
if (window.sessionStorage) {
$('.navbar .navbar-collapse>.navbar-nav a').on('click', function (e) {
sessionStorage.setItem('AppHome._InTab', e.target.href.split('?')[1])
})
Expand Down
Loading
Loading