Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in / Register
Toggle navigation
Y
yzg-util
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
YZG
yzg-util
Commits
a56dedd6
Commit
a56dedd6
authored
May 12, 2022
by
yanzg
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
修复等待时间
parent
b8b78355
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
115 additions
and
85 deletions
+115
-85
YzgTimeout.java
...src/main/java/com/yanzuoguang/util/helper/YzgTimeout.java
+48
-0
BaseDaoSql.java
...db/src/main/java/com/yanzuoguang/dao/impl/BaseDaoSql.java
+8
-5
DbExecuteImpl.java
.../src/main/java/com/yanzuoguang/db/impl/DbExecuteImpl.java
+46
-42
BeanDao.java
...util-mq/src/main/java/com/yanzuoguang/mq/dao/BeanDao.java
+4
-32
MessageDaoImpl.java
...main/java/com/yanzuoguang/mq/dao/impl/MessageDaoImpl.java
+9
-6
No files found.
yzg-util-base/src/main/java/com/yanzuoguang/util/helper/YzgTimeout.java
0 → 100644
View file @
a56dedd6
package
com
.
yanzuoguang
.
util
.
helper
;
import
com.yanzuoguang.util.log.Log
;
import
com.yanzuoguang.util.thread.ThreadHelper
;
import
com.yanzuoguang.util.vo.Ref
;
/**
* 超时监控
*
* @author 颜佐光
*/
public
class
YzgTimeout
{
public
static
final
long
TIME_OUT_DEFAULT
=
5000
;
public
static
final
int
TIME_OUT_TIP
=
1000
;
/**
* 超时监控
*
* @param cls 日志类
* @param message 消息
* @param runnable 运行函数
*/
public
static
void
timeOut
(
Class
<?>
cls
,
String
message
,
Runnable
runnable
)
{
final
Ref
<
Boolean
>
isRun
=
new
Ref
<>(
false
);
ThreadHelper
.
runThread
(()
->
{
try
{
long
timeMax
=
TIME_OUT_DEFAULT
;
int
timeUnit
=
10
;
long
start
=
System
.
currentTimeMillis
();
do
{
ThreadHelper
.
sleep
(
timeUnit
);
long
end
=
System
.
currentTimeMillis
();
if
(
end
-
start
>
timeMax
)
{
timeUnit
=
TIME_OUT_TIP
;
Log
.
error
(
cls
,
message
+
"超时,正在等待执行完成"
);
}
}
while
(!
isRun
.
value
);
}
catch
(
Exception
ex
)
{
ex
.
printStackTrace
();
}
finally
{
Log
.
info
(
cls
,
message
+
"完成"
);
}
});
runnable
.
run
();
isRun
.
value
=
true
;
}
}
yzg-util-db/src/main/java/com/yanzuoguang/dao/impl/BaseDaoSql.java
View file @
a56dedd6
...
@@ -11,9 +11,12 @@ import com.yanzuoguang.util.cache.MemoryCache;
...
@@ -11,9 +11,12 @@ import com.yanzuoguang.util.cache.MemoryCache;
import
com.yanzuoguang.util.helper.ArrayHelper
;
import
com.yanzuoguang.util.helper.ArrayHelper
;
import
com.yanzuoguang.util.helper.StringFormatHandle
;
import
com.yanzuoguang.util.helper.StringFormatHandle
;
import
com.yanzuoguang.util.helper.StringHelper
;
import
com.yanzuoguang.util.helper.StringHelper
;
import
com.yanzuoguang.util.vo.*
;
import
com.yanzuoguang.util.vo.MapRow
;
import
com.yanzuoguang.util.vo.PageSizeData
;
import
com.yanzuoguang.util.vo.PageSizeReq
;
import
com.yanzuoguang.util.vo.PageSizeReqVo
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
javax.annotation.Resource
;
import
java.util.*
;
import
java.util.*
;
import
java.util.regex.Matcher
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
import
java.util.regex.Pattern
;
...
@@ -69,7 +72,7 @@ public abstract class BaseDaoSql {
...
@@ -69,7 +72,7 @@ public abstract class BaseDaoSql {
this
.
init
();
this
.
init
();
}
}
@
Resource
@
Autowired
public
void
setDb
(
DbExecute
db
)
{
public
void
setDb
(
DbExecute
db
)
{
this
.
db
=
db
;
this
.
db
=
db
;
}
}
...
@@ -87,8 +90,8 @@ public abstract class BaseDaoSql {
...
@@ -87,8 +90,8 @@ public abstract class BaseDaoSql {
return
table
;
return
table
;
}
}
protected
void
checkTable
(){
protected
void
checkTable
()
{
if
(
this
.
table
==
null
)
{
if
(
this
.
table
==
null
)
{
throw
YzgError
.
getRuntimeException
(
"002"
);
throw
YzgError
.
getRuntimeException
(
"002"
);
}
}
}
}
...
...
yzg-util-db/src/main/java/com/yanzuoguang/db/impl/DbExecuteImpl.java
View file @
a56dedd6
...
@@ -2,18 +2,15 @@ package com.yanzuoguang.db.impl;
...
@@ -2,18 +2,15 @@ package com.yanzuoguang.db.impl;
import
com.yanzuoguang.db.ConfigDb
;
import
com.yanzuoguang.db.ConfigDb
;
import
com.yanzuoguang.db.DbExecute
;
import
com.yanzuoguang.db.DbExecute
;
import
com.yanzuoguang.util.helper.YzgTimeout
;
import
com.yanzuoguang.util.vo.MapRow
;
import
com.yanzuoguang.util.vo.MapRow
;
import
com.yanzuoguang.util.vo.Ref
;
import
com.yanzuoguang.util.vo.Ref
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.context.annotation.Lazy
;
import
org.springframework.beans.factory.annotation.Qualifier
;
import
org.springframework.jdbc.core.JdbcTemplate
;
import
org.springframework.jdbc.core.JdbcTemplate
;
import
org.springframework.jdbc.core.RowCallbackHandler
;
import
org.springframework.jdbc.core.RowCallbackHandler
;
import
org.springframework.jdbc.support.rowset.SqlRowSet
;
import
org.springframework.jdbc.support.rowset.SqlRowSet
;
import
org.springframework.stereotype.Component
;
import
org.springframework.stereotype.Component
;
import
javax.annotation.Resource
;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.List
;
...
@@ -25,18 +22,18 @@ import java.util.List;
...
@@ -25,18 +22,18 @@ import java.util.List;
@Component
@Component
public
class
DbExecuteImpl
implements
DbExecute
{
public
class
DbExecuteImpl
implements
DbExecute
{
@Resource
private
final
JdbcTemplate
jdbcTemplate
;
@Qualifier
(
"jdbcTemplate"
)
private
final
DbPrintSql
printSql
;
private
JdbcTemplate
jdbc
;
private
final
ConfigDb
configDb
;
@Autowired
public
DbExecuteImpl
(
JdbcTemplate
jdbcTemplate
,
DbPrintSql
printSql
,
ConfigDb
configDb
)
{
private
DbPrintSql
printSql
;
this
.
jdbcTemplate
=
jdbcTemplate
;
this
.
printSql
=
printSql
;
@Autowired
this
.
configDb
=
configDb
;
private
ConfigDb
configDb
;
}
public
JdbcTemplate
getJdbc
()
{
public
JdbcTemplate
getJdbc
()
{
return
jdbc
;
return
jdbc
Template
;
}
}
/**
/**
...
@@ -50,14 +47,15 @@ public class DbExecuteImpl implements DbExecute {
...
@@ -50,14 +47,15 @@ public class DbExecuteImpl implements DbExecute {
*/
*/
@Override
@Override
public
int
update
(
Class
targetClass
,
String
sqlName
,
String
sql
,
Object
...
paras
)
{
public
int
update
(
Class
targetClass
,
String
sqlName
,
String
sql
,
Object
...
paras
)
{
int
row
=
0
;
Ref
<
Integer
>
row
=
new
Ref
<>(
0
)
;
long
start
=
System
.
currentTimeMillis
();
long
start
=
System
.
currentTimeMillis
();
try
{
try
{
sql
=
this
.
handleParas
(
sql
,
paras
);
sql
=
this
.
handleParas
(
sql
,
paras
);
row
=
this
.
getJdbc
().
update
(
sql
,
paras
);
String
finalSql
=
sql
;
return
row
;
YzgTimeout
.
timeOut
(
DbExecuteImpl
.
class
,
sqlName
,
()
->
row
.
value
=
getJdbc
().
update
(
finalSql
,
paras
));
return
row
.
value
;
}
finally
{
}
finally
{
printSql
.
print
(
targetClass
,
sqlName
,
start
,
row
,
sql
,
paras
);
printSql
.
print
(
targetClass
,
sqlName
,
start
,
row
.
value
,
sql
,
paras
);
}
}
}
}
...
@@ -78,16 +76,16 @@ public class DbExecuteImpl implements DbExecute {
...
@@ -78,16 +76,16 @@ public class DbExecuteImpl implements DbExecute {
long
start
=
System
.
currentTimeMillis
();
long
start
=
System
.
currentTimeMillis
();
try
{
try
{
sql
=
this
.
handleParas
(
sql
,
paras
);
sql
=
this
.
handleParas
(
sql
,
paras
);
RowCallbackHandler
rowCallbackHandler
=
new
RowCallbackHandler
()
{
String
finalSql
=
sql
;
@Override
YzgTimeout
.
timeOut
(
DbExecuteImpl
.
class
,
sqlName
,
()
->
{
public
void
processRow
(
ResultSet
rs
)
throws
SQLException
{
RowCallbackHandler
rowCallbackHandler
=
rs
->
{
AllBeanRowMapper
<
T
>
rowMap
=
AllBeanRowMapper
.
getInstance
(
cls
,
configDb
);
AllBeanRowMapper
<
T
>
rowMap
=
AllBeanRowMapper
.
getInstance
(
cls
,
configDb
);
T
data
=
rowMap
.
mapRow
(
rs
,
row
.
value
);
T
data
=
rowMap
.
mapRow
(
rs
,
row
.
value
);
rowHandle
.
handle
(
data
);
rowHandle
.
handle
(
data
);
row
.
value
++;
row
.
value
++;
}
}
;
}
;
this
.
getJdbc
().
query
(
finalSql
,
rowCallbackHandler
,
paras
)
;
this
.
getJdbc
().
query
(
sql
,
rowCallbackHandler
,
paras
);
}
);
}
finally
{
}
finally
{
printSql
.
print
(
targetClass
,
sqlName
,
start
,
row
.
value
,
sql
,
paras
);
printSql
.
print
(
targetClass
,
sqlName
,
start
,
row
.
value
,
sql
,
paras
);
}
}
...
@@ -111,12 +109,17 @@ public class DbExecuteImpl implements DbExecute {
...
@@ -111,12 +109,17 @@ public class DbExecuteImpl implements DbExecute {
long
start
=
System
.
currentTimeMillis
();
long
start
=
System
.
currentTimeMillis
();
try
{
try
{
sql
=
this
.
handleParas
(
sql
,
paras
);
sql
=
this
.
handleParas
(
sql
,
paras
);
List
<
T
>
ret
=
this
.
getJdbc
().
query
(
sql
,
paras
,
AllBeanRowMapper
.
getInstance
(
cls
,
configDb
));
Ref
<
List
<
T
>>
ret
=
new
Ref
<>(
null
);
if
(
ret
==
null
)
{
ret
=
new
ArrayList
<
T
>();
String
finalSql
=
sql
;
YzgTimeout
.
timeOut
(
cls
,
sqlName
,
()
->
{
ret
.
value
=
this
.
getJdbc
().
query
(
finalSql
,
paras
,
AllBeanRowMapper
.
getInstance
(
cls
,
configDb
));
});
if
(
ret
.
value
==
null
)
{
ret
.
value
=
new
ArrayList
<
T
>();
}
}
row
=
ret
.
size
();
row
=
ret
.
value
.
size
();
return
ret
;
return
ret
.
value
;
}
finally
{
}
finally
{
printSql
.
print
(
targetClass
,
sqlName
,
start
,
row
,
sql
,
paras
);
printSql
.
print
(
targetClass
,
sqlName
,
start
,
row
,
sql
,
paras
);
}
}
...
@@ -147,18 +150,24 @@ public class DbExecuteImpl implements DbExecute {
...
@@ -147,18 +150,24 @@ public class DbExecuteImpl implements DbExecute {
*/
*/
@Override
@Override
public
Object
queryCell
(
Class
targetClass
,
String
sqlName
,
String
sql
,
Object
...
paras
)
{
public
Object
queryCell
(
Class
targetClass
,
String
sqlName
,
String
sql
,
Object
...
paras
)
{
int
row
=
0
;
Ref
<
Integer
>
row
=
new
Ref
<>(
0
)
;
long
start
=
System
.
currentTimeMillis
();
long
start
=
System
.
currentTimeMillis
();
try
{
try
{
sql
=
this
.
handleParas
(
sql
,
paras
);
sql
=
this
.
handleParas
(
sql
,
paras
);
SqlRowSet
rowSet
=
this
.
getJdbc
().
queryForRowSet
(
sql
,
paras
);
Ref
<
Object
>
ret
=
new
Ref
<>(
null
);
while
(
rowSet
.
next
())
{
row
=
1
;
String
finalSql
=
sql
;
return
rowSet
.
getObject
(
1
);
YzgTimeout
.
timeOut
(
DbExecuteImpl
.
class
,
sqlName
,
()
->
{
}
SqlRowSet
rowSet
=
this
.
getJdbc
().
queryForRowSet
(
finalSql
,
paras
);
while
(
rowSet
.
next
())
{
row
.
value
=
1
;
ret
.
value
=
rowSet
.
getObject
(
1
);
break
;
}
});
return
null
;
return
null
;
}
finally
{
}
finally
{
printSql
.
print
(
targetClass
,
sqlName
,
start
,
row
,
sql
,
paras
);
printSql
.
print
(
targetClass
,
sqlName
,
start
,
row
.
value
,
sql
,
paras
);
}
}
}
}
...
@@ -170,11 +179,6 @@ public class DbExecuteImpl implements DbExecute {
...
@@ -170,11 +179,6 @@ public class DbExecuteImpl implements DbExecute {
* @return
* @return
*/
*/
protected
String
handleParas
(
String
sql
,
Object
...
paras
)
{
protected
String
handleParas
(
String
sql
,
Object
...
paras
)
{
return
sql
.
replaceAll
(
"1\\s*?=\\s*?1\\s*?(?i)AND"
,
""
)
return
sql
.
replaceAll
(
"1\\s*?=\\s*?1\\s*?(?i)AND"
,
""
).
replaceAll
(
"(?i)WHERE\\s*?1\\s*?=\\s*?1"
,
""
).
replaceAll
(
"((?i)ORDER\\s*?(?i)BY\\s*?)1\\s*?,"
,
"$1"
).
replaceAll
(
"(?i)ORDER\\s*?(?i)BY\\s*?1\\s*?"
,
""
).
replaceAll
(
"((?i)GROUP\\s*?(?i)BY\\s*?)1\\s*?,"
,
"$1"
).
replaceAll
(
"(?i)GROUP\\s*?(?i)BY\\s*?1\\s*?"
,
""
);
.
replaceAll
(
"(?i)WHERE\\s*?1\\s*?=\\s*?1"
,
""
)
.
replaceAll
(
"((?i)ORDER\\s*?(?i)BY\\s*?)1\\s*?,"
,
"$1"
)
.
replaceAll
(
"(?i)ORDER\\s*?(?i)BY\\s*?1\\s*?"
,
""
)
.
replaceAll
(
"((?i)GROUP\\s*?(?i)BY\\s*?)1\\s*?,"
,
"$1"
)
.
replaceAll
(
"(?i)GROUP\\s*?(?i)BY\\s*?1\\s*?"
,
""
);
}
}
}
}
yzg-util-mq/src/main/java/com/yanzuoguang/mq/dao/BeanDao.java
View file @
a56dedd6
...
@@ -3,9 +3,7 @@ package com.yanzuoguang.mq.dao;
...
@@ -3,9 +3,7 @@ package com.yanzuoguang.mq.dao;
import
com.yanzuoguang.dao.DaoConst
;
import
com.yanzuoguang.dao.DaoConst
;
import
com.yanzuoguang.util.YzgError
;
import
com.yanzuoguang.util.YzgError
;
import
com.yanzuoguang.util.helper.StringHelper
;
import
com.yanzuoguang.util.helper.StringHelper
;
import
com.yanzuoguang.util.log.Log
;
import
com.yanzuoguang.util.helper.YzgTimeout
;
import
com.yanzuoguang.util.thread.ThreadHelper
;
import
com.yanzuoguang.util.vo.Ref
;
import
org.springframework.amqp.core.*
;
import
org.springframework.amqp.core.*
;
import
org.springframework.beans.factory.support.DefaultListableBeanFactory
;
import
org.springframework.beans.factory.support.DefaultListableBeanFactory
;
import
org.springframework.context.ApplicationContext
;
import
org.springframework.context.ApplicationContext
;
...
@@ -113,7 +111,7 @@ public class BeanDao {
...
@@ -113,7 +111,7 @@ public class BeanDao {
ex
.
printStackTrace
();
ex
.
printStackTrace
();
}
}
if
(
isCreateQueue
)
{
if
(
isCreateQueue
)
{
this
.
timeOut
(
Queue
.
class
,
queueName
,
"创建队列"
,
()
->
amqpAdmin
.
declareQueue
(
queueNew
));
YzgTimeout
.
timeOut
(
BeanDao
.
class
,
"创建队列"
+
queueName
,
()
->
amqpAdmin
.
declareQueue
(
queueNew
));
}
}
// 将实体注册到上下文中
// 将实体注册到上下文中
register
(
key
,
queueNew
);
register
(
key
,
queueNew
);
...
@@ -137,7 +135,7 @@ public class BeanDao {
...
@@ -137,7 +135,7 @@ public class BeanDao {
// 创建实体
// 创建实体
TopicExchange
bean
=
new
TopicExchange
(
exchangeName
,
true
,
false
);
TopicExchange
bean
=
new
TopicExchange
(
exchangeName
,
true
,
false
);
this
.
timeOut
(
TopicExchange
.
class
,
bean
.
getName
(),
"创建交换器"
,
()
->
amqpAdmin
.
declareExchange
(
bean
));
YzgTimeout
.
timeOut
(
BeanDao
.
class
,
"创建交换器"
+
exchangeName
,
()
->
amqpAdmin
.
declareExchange
(
bean
));
// 将实体注册到上下文中
// 将实体注册到上下文中
register
(
key
,
bean
);
register
(
key
,
bean
);
...
@@ -155,7 +153,7 @@ public class BeanDao {
...
@@ -155,7 +153,7 @@ public class BeanDao {
*/
*/
public
Binding
createBinding
(
String
exchangeName
,
String
queueName
,
String
routeKey
)
{
public
Binding
createBinding
(
String
exchangeName
,
String
queueName
,
String
routeKey
)
{
Binding
binding
=
BindingBuilder
.
bind
(
getQueue
(
queueName
)).
to
(
getExchange
(
exchangeName
)).
with
(
routeKey
);
Binding
binding
=
BindingBuilder
.
bind
(
getQueue
(
queueName
)).
to
(
getExchange
(
exchangeName
)).
with
(
routeKey
);
this
.
timeOut
(
TopicExchange
.
class
,
binding
.
getRoutingKey
(),
"创建路由绑定"
,
()
->
amqpAdmin
.
declareBinding
(
binding
));
YzgTimeout
.
timeOut
(
BeanDao
.
class
,
"创建路由绑定"
+
routeKey
,
()
->
amqpAdmin
.
declareBinding
(
binding
));
return
binding
;
return
binding
;
}
}
...
@@ -191,31 +189,5 @@ public class BeanDao {
...
@@ -191,31 +189,5 @@ public class BeanDao {
defaultListableBeanFactory
.
registerSingleton
(
name
,
target
);
defaultListableBeanFactory
.
registerSingleton
(
name
,
target
);
}
}
private
void
timeOut
(
Class
<?>
cls
,
String
name
,
String
message
,
Runnable
runnable
)
{
final
Ref
<
Boolean
>
isRun
=
new
Ref
<>(
false
);
ThreadHelper
.
runThread
(()
->
{
try
{
long
timeMax
=
1000
;
int
timeUnit
=
10
;
long
start
=
System
.
currentTimeMillis
();
do
{
ThreadHelper
.
sleep
(
timeUnit
);
long
end
=
System
.
currentTimeMillis
();
if
(
end
-
start
>
timeMax
)
{
timeUnit
=
1000
;
Log
.
error
(
cls
,
message
+
name
+
"超时,正在等待执行完成"
);
}
}
while
(!
isRun
.
value
);
}
catch
(
Exception
ex
)
{
ex
.
printStackTrace
();
}
finally
{
Log
.
info
(
cls
,
message
+
name
+
"完成"
);
}
});
runnable
.
run
();
isRun
.
value
=
true
;
}
}
}
yzg-util-mq/src/main/java/com/yanzuoguang/mq/dao/impl/MessageDaoImpl.java
View file @
a56dedd6
...
@@ -5,6 +5,7 @@ import com.yanzuoguang.dao.impl.BaseDaoImpl;
...
@@ -5,6 +5,7 @@ import com.yanzuoguang.dao.impl.BaseDaoImpl;
import
com.yanzuoguang.dao.impl.SqlData
;
import
com.yanzuoguang.dao.impl.SqlData
;
import
com.yanzuoguang.mq.dao.MessageDao
;
import
com.yanzuoguang.mq.dao.MessageDao
;
import
com.yanzuoguang.mq.vo.MessageVo
;
import
com.yanzuoguang.mq.vo.MessageVo
;
import
com.yanzuoguang.util.helper.YzgTimeout
;
import
com.yanzuoguang.util.vo.MapRow
;
import
com.yanzuoguang.util.vo.MapRow
;
import
org.springframework.beans.factory.InitializingBean
;
import
org.springframework.beans.factory.InitializingBean
;
import
org.springframework.stereotype.Component
;
import
org.springframework.stereotype.Component
;
...
@@ -64,12 +65,14 @@ public class MessageDaoImpl extends BaseDaoImpl implements MessageDao, Initializ
...
@@ -64,12 +65,14 @@ public class MessageDaoImpl extends BaseDaoImpl implements MessageDao, Initializ
*/
*/
@Override
@Override
public
void
afterPropertiesSet
()
throws
Exception
{
public
void
afterPropertiesSet
()
throws
Exception
{
List
<
MapRow
>
tables
=
this
.
getDb
().
query
(
MessageDaoImpl
.
class
,
"QUERY_TABLE_SQL"
,
QUERY_TABLE_SQL
);
YzgTimeout
.
timeOut
(
MessageDaoImpl
.
class
,
"消息队列处理工具类初始化"
,
()
->
{
if
(
tables
.
isEmpty
())
{
List
<
MapRow
>
tables
=
this
.
getDb
().
query
(
MessageDaoImpl
.
class
,
"QUERY_TABLE_SQL"
,
QUERY_TABLE_SQL
);
this
.
getDb
().
update
(
MessageDaoImpl
.
class
,
"CREATE_TABLE_SQL"
,
CREATE_TABLE_SQL
);
if
(
tables
.
isEmpty
())
{
}
else
{
this
.
getDb
().
update
(
MessageDaoImpl
.
class
,
"CREATE_TABLE_SQL"
,
CREATE_TABLE_SQL
);
this
.
getDb
().
update
(
MessageDaoImpl
.
class
,
"ALTER_TABLE_SQL"
,
ALTER_TABLE_SQL
);
}
else
{
}
this
.
getDb
().
update
(
MessageDaoImpl
.
class
,
"ALTER_TABLE_SQL"
,
ALTER_TABLE_SQL
);
}
});
}
}
/**
/**
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment