1
1
package com .wizzardo .techempower ;
2
2
3
+ import com .wizzardo .epoll .ByteBufferProvider ;
4
+ import com .wizzardo .epoll .ByteBufferWrapper ;
5
+ import com .wizzardo .http .HttpConnection ;
3
6
import com .wizzardo .http .framework .Controller ;
4
- import com .wizzardo .http .framework .parameters .Parameter ;
5
7
import com .wizzardo .http .framework .template .Renderer ;
6
8
import com .wizzardo .http .request .Header ;
9
+ import com .wizzardo .http .response .Status ;
10
+ import com .wizzardo .tools .json .JsonTools ;
7
11
8
- import java .nio .charset .StandardCharsets ;
9
- import java .sql .Connection ;
10
- import java .sql .PreparedStatement ;
11
- import java .sql .ResultSet ;
12
- import java .sql .SQLException ;
13
- import java .util .ArrayList ;
14
- import java .util .Collections ;
15
- import java .util .List ;
12
+ import java .sql .*;
13
+ import java .util .Arrays ;
14
+ import java .util .concurrent .ExecutorService ;
15
+ import java .util .concurrent .Executors ;
16
16
import java .util .concurrent .ThreadLocalRandom ;
17
+ import java .util .concurrent .atomic .AtomicBoolean ;
18
+ import java .util .concurrent .atomic .AtomicInteger ;
17
19
18
20
public class DBController extends Controller {
19
21
20
22
DBService dbService ;
23
+ static ThreadLocal <ByteBufferProvider > byteBufferProviderThreadLocal = ThreadLocal .<ByteBufferProvider >withInitial (() -> {
24
+ ByteBufferWrapper wrapper = new ByteBufferWrapper (64 * 1024 );
25
+ return () -> wrapper ;
26
+ });
27
+
28
+ static ExecutorService executorService = Executors .newFixedThreadPool (Runtime .getRuntime ().availableProcessors ());
21
29
22
30
public Renderer world () throws SQLException {
23
31
World world ;
@@ -36,52 +44,112 @@ public Renderer world() throws SQLException {
36
44
return renderJson (world );
37
45
}
38
46
39
- public Renderer queries () throws SQLException {
47
+ public void queries () {
40
48
int queries = Math .min (Math .max (params ().getInt ("queries" , 1 ), 1 ), 500 );
49
+ response .async ();
50
+ AtomicInteger counter = new AtomicInteger (0 );
51
+ AtomicBoolean failed = new AtomicBoolean (false );
41
52
42
53
World [] worlds = new World [queries ];
43
- try (Connection connection = dbService .getConnection ();
44
- PreparedStatement statement = connection .prepareStatement ("SELECT id,randomNumber FROM World WHERE id = ?" )
45
- ) {
46
- for (int i = 0 ; i < worlds .length ; i ++) {
47
- statement .setInt (1 , getRandomNumber ());
48
- try (ResultSet resultSet = statement .executeQuery ()) {
49
- resultSet .next ();
50
- int id = resultSet .getInt (1 );
51
- int randomNumber = resultSet .getInt (2 );
52
- worlds [i ] = new World (id , randomNumber );
53
- }
54
- }
55
- }
56
-
57
- return renderJson (worlds );
58
- }
54
+ for (int i = 0 ; i < queries ; i ++) {
55
+ int index = i ;
59
56
60
- public Renderer updates () throws SQLException {
61
- int queries = Math .min (Math .max (params ().getInt ("queries" , 1 ), 1 ), 500 );
62
- World [] worlds = new World [queries ];
63
- try (Connection connection = dbService .getConnection ()) {
64
- try (PreparedStatement statement = connection .prepareStatement ("SELECT id,randomNumber FROM World WHERE id = ?" )) {
65
- for (int i = 0 ; i < worlds .length ; i ++) {
57
+ executorService .submit (() -> {
58
+ try (Connection connection = dbService .getConnection ();
59
+ PreparedStatement statement = connection .prepareStatement ("SELECT id,randomNumber FROM World WHERE id = ?" )
60
+ ) {
66
61
statement .setInt (1 , getRandomNumber ());
67
62
try (ResultSet resultSet = statement .executeQuery ()) {
68
63
resultSet .next ();
69
64
int id = resultSet .getInt (1 );
70
65
int randomNumber = resultSet .getInt (2 );
71
- worlds [i ] = new World (id , randomNumber );
66
+ worlds [index ] = new World (id , randomNumber );
67
+ }
68
+ } catch (SQLException e ) {
69
+ if (failed .compareAndSet (false , true )) {
70
+ response .status (Status ._500 ).body (e .getMessage ());
71
+ commitAsyncResponse ();
72
72
}
73
+ return ;
73
74
}
74
- }
75
- try (PreparedStatement statement = connection .prepareStatement ("UPDATE World SET randomNumber = ? WHERE id = ?" )) {
76
- for (World world : worlds ) {
77
- world .randomNumber = getRandomNumber ();
78
- statement .setInt (1 , world .randomNumber );
79
- statement .setInt (2 , world .id );
80
- statement .executeUpdate ();
75
+
76
+ if (counter .incrementAndGet () == queries && !failed .get ()) {
77
+ response .appendHeader (Header .KV_CONTENT_TYPE_APPLICATION_JSON );
78
+ response .body (JsonTools .serializeToBytes (worlds ));
79
+
80
+ commitAsyncResponse ();
81
81
}
82
- }
82
+ });
83
83
}
84
- return renderJson (worlds );
84
+ }
85
+
86
+ public void updates () {
87
+ int queries = Math .min (Math .max (params ().getInt ("queries" , 1 ), 1 ), 500 );
88
+ response .async ();
89
+ AtomicInteger counter = new AtomicInteger (0 );
90
+ AtomicBoolean failed = new AtomicBoolean (false );
91
+
92
+ World [] worlds = new World [queries ];
93
+ for (int i = 0 ; i < queries ; i ++) {
94
+ int index = i ;
95
+ executorService .submit (() -> {
96
+ try (Connection connection = dbService .getConnection ()) {
97
+ try (PreparedStatement statement = connection .prepareStatement ("SELECT id,randomNumber FROM World WHERE id = ?" )) {
98
+ statement .setInt (1 , getRandomNumber ());
99
+ try (ResultSet resultSet = statement .executeQuery ()) {
100
+ resultSet .next ();
101
+ int id = resultSet .getInt (1 );
102
+ int randomNumber = resultSet .getInt (2 );
103
+ worlds [index ] = new World (id , randomNumber );
104
+ }
105
+ }
106
+ } catch (Exception e ) {
107
+ if (failed .compareAndSet (false , true )) {
108
+ response .status (Status ._500 ).body (e .getMessage ());
109
+ commitAsyncResponse ();
110
+ }
111
+ }
112
+
113
+
114
+ if (counter .incrementAndGet () == queries && !failed .get ()) {
115
+ executorService .submit (() -> {
116
+ try (Connection connection = dbService .getConnection ()) {
117
+ try (PreparedStatement statement = connection .prepareStatement ("UPDATE World SET randomNumber = ? WHERE id = ?" )) {
118
+ Arrays .sort (worlds , (o1 , o2 ) -> Integer .compare (o2 .id , o1 .id ));
119
+ for (int j = queries - 1 ; j >= 0 ; j --) {
120
+ World world = worlds [j ];
121
+ world .randomNumber = getRandomNumber ();
122
+ statement .setInt (1 , world .randomNumber );
123
+ statement .setInt (2 , world .id );
124
+ if (j > 0 )
125
+ statement .addBatch ();
126
+ else
127
+ statement .executeBatch ();
128
+ }
129
+ }
130
+
131
+ response .appendHeader (Header .KV_CONTENT_TYPE_APPLICATION_JSON );
132
+ response .body (JsonTools .serializeToBytes (worlds ));
133
+
134
+ commitAsyncResponse ();
135
+ } catch (Exception e ) {
136
+ if (failed .compareAndSet (false , true )) {
137
+ response .status (Status ._500 ).body (e .getMessage ());
138
+ commitAsyncResponse ();
139
+ }
140
+ }
141
+ });
142
+ }
143
+ });
144
+ }
145
+ }
146
+
147
+ protected void commitAsyncResponse () {
148
+ ByteBufferProvider bufferProvider = byteBufferProviderThreadLocal .get ();
149
+ HttpConnection connection = request .connection ();
150
+ response .commit (connection , bufferProvider );
151
+ connection .flush (bufferProvider );
152
+ response .reset ();
85
153
}
86
154
87
155
protected int getRandomNumber () {
0 commit comments