11
11
import java .io .OutputStream ;
12
12
import java .nio .channels .Channels ;
13
13
import java .nio .channels .FileChannel ;
14
+ import java .nio .channels .FileLock ;
14
15
import java .nio .charset .StandardCharsets ;
15
16
import java .nio .file .StandardOpenOption ;
16
17
import java .util .ArrayList ;
17
- import java .util .Arrays ;
18
18
import java .util .Collections ;
19
19
import java .util .Date ;
20
20
import java .util .List ;
25
25
import java .util .concurrent .locks .Lock ;
26
26
import java .util .concurrent .locks .ReentrantLock ;
27
27
import java .util .stream .Collectors ;
28
+ import org .apache .commons .io .FileSystem ;
28
29
29
30
public class FallbackAppender {
30
31
@@ -86,25 +87,18 @@ public void run() {
86
87
}
87
88
88
89
List <Message > msgs ;
89
- lock .lock ();
90
90
try {
91
- msgs = read ();
91
+ msgs = truncate ( 20 ); // XXX messageSize
92
92
if (msgs .isEmpty ()) {
93
93
continue ;
94
94
}
95
- // FIXME now its reading all the msgs and waits until all is processed
96
- // it will be better to work with batch and truncate the file
97
- file .delete ();
98
95
} catch (IOException e ) {
99
96
// TODO Auto-generated catch block
100
97
e .printStackTrace ();
101
98
lastMessage = System .currentTimeMillis ();
102
99
continue ;
103
- } finally {
104
- lock .unlock ();
105
100
}
106
101
107
- // FIXME batch
108
102
while (!msgs .isEmpty ()) {
109
103
boolean canEnqueue = true ;
110
104
for (int i = msgs .size () - 1 ; canEnqueue && i >= 0 ; i --) {
@@ -113,16 +107,16 @@ public void run() {
113
107
if (canEnqueue ) {
114
108
msgs .remove (i );
115
109
System .err .println ("reenqueued " + msg .messageId ());
110
+ } else {
111
+ // slow down next iteration when http queue overflow
112
+ try {
113
+ Thread .sleep (1_000 );
114
+ } catch (InterruptedException e ) {
115
+ Thread .currentThread ().interrupt ();
116
+ }
116
117
}
117
118
}
118
- try {
119
- Thread .sleep (1_000 );
120
- } catch (InterruptedException e ) {
121
- Thread .currentThread ().interrupt ();
122
- }
123
119
}
124
-
125
- lastMessage = System .currentTimeMillis ();
126
120
}
127
121
128
122
try {
@@ -161,38 +155,43 @@ public void run() {
161
155
}
162
156
}
163
157
164
- List <Message > read () throws IOException {
165
- if (file .exists ()) {
166
- try (FileChannel fileChannel = FileChannel .open (file .toPath (), StandardOpenOption .READ )) {
167
- fileChannel .lock (0 , Long .MAX_VALUE , true );
168
-
169
- final String [] lines = new String (
170
- Channels .newInputStream (fileChannel ).readAllBytes (), StandardCharsets .UTF_8 )
171
- .split (System .lineSeparator ());
172
- return Arrays .stream (lines )
173
- .map (m -> fromJson (m ))
174
- .filter (Objects ::nonNull )
175
- .collect (Collectors .toList ());
176
- }
177
- } else {
158
+ List <Message > truncate (int numMessages ) throws IOException {
159
+ lock .lock ();
160
+
161
+ if (!file .exists ()) {
162
+ lock .unlock ();
178
163
return Collections .emptyList ();
179
164
}
165
+
166
+ try (ReversedLinesFileReader reader = ReversedLinesFileReader .builder ()
167
+ .setPath (file .toPath ())
168
+ .setBufferSize (FileSystem .getCurrent ().getBlockSize ())
169
+ .setCharset (StandardCharsets .UTF_8 )
170
+ .get ()) {
171
+
172
+ return reader .readLines (numMessages ).stream ()
173
+ .map (this ::fromJson )
174
+ .filter (Objects ::nonNull )
175
+ .collect (Collectors .toList ());
176
+ } finally {
177
+ lock .unlock ();
178
+ }
180
179
}
181
180
181
+ private static final byte [] NEW_LINE = System .lineSeparator ().getBytes (StandardCharsets .UTF_8 );
182
+
182
183
private void write (List <Message > batch ) {
183
184
lock .lock ();
184
185
try (FileChannel fileChannel = FileChannel .open (
185
- file .toPath (), StandardOpenOption .WRITE , StandardOpenOption .APPEND , StandardOpenOption .CREATE )) {
186
- fileChannel .lock ();
186
+ file .toPath (), StandardOpenOption .WRITE , StandardOpenOption .APPEND , StandardOpenOption .CREATE );
187
+ OutputStream os = Channels .newOutputStream (fileChannel );
188
+ FileLock fileLock = fileChannel .lock (); ) {
187
189
188
- final String lines = batch . stream ()
189
- . map ( this :: toJson )
190
- . filter ( Objects :: nonNull )
191
- . collect ( Collectors . joining ( System . lineSeparator ()));
190
+ for ( Message msg : batch ) {
191
+ os . write ( toJson ( msg ). getBytes ( StandardCharsets . UTF_8 ));
192
+ os . write ( NEW_LINE );
193
+ }
192
194
193
- OutputStream os = Channels .newOutputStream (fileChannel );
194
- os .write (lines .getBytes (StandardCharsets .UTF_8 ));
195
- os .write (System .lineSeparator ().getBytes (StandardCharsets .UTF_8 ));
196
195
fileChannel .force (true );
197
196
198
197
batch .clear ();
0 commit comments