Last active
June 30, 2020 12:46
A fairly naive implementation of a slow InputStream. Useful for simulating slow HTTP servers in Ring apps. Also shows how to proxy overloaded methods.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defn slow-stream | |
"Returns an implementation of InputStream that takes `time` | |
milliseconds to return a random buffer of `size` bytes." | |
[time size] | |
(let [first-read (atom nil) | |
bytes-read (atom 0) | |
rate (/ (double time) size)] | |
(proxy [java.io.InputStream] [] | |
(read ^int | |
([] | |
(let [now (System/currentTimeMillis)] | |
(when-not @first-read (reset! first-read now)) | |
(let [sleep-to (+ @first-read (long (* rate @bytes-read))) | |
sleep-for (- sleep-to now)] | |
(when (pos? sleep-for) | |
(Thread/sleep sleep-for)))) | |
(let [result (if (< @bytes-read size) (+ 65 128 (rand-int 26)) -1)] | |
(swap! bytes-read inc) | |
result)) | |
;; TODO: This is behaving strangely. Test further. | |
([^bytes bytes] | |
(let [first-b (.read this)] | |
(if (neg? first-b) | |
-1 | |
(loop [b first-b | |
bytes-read 1] | |
(if (neg? b) | |
(dec bytes-read) | |
(do | |
(aset bytes (dec bytes-read) (byte (- b 128))) | |
(if (< bytes-read (alength bytes)) | |
(recur (.read this) (inc bytes-read)) | |
bytes-read))))))))))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// A Java variation on the same theme | |
package user; | |
import java.io.InputStream; | |
import java.util.Random; | |
public class SlowInputStream extends InputStream { | |
private final long time; | |
private final long size; | |
private final double rate; | |
private final Random random = new Random(); | |
private long first_read = -1; | |
private long bytes_read = 0; | |
public SlowInputStream(int time, int size) { | |
this.time = time; | |
this.size = size; | |
this.rate = Double.valueOf(time) / size; | |
} | |
@Override | |
public int read() { | |
long now = System.currentTimeMillis(); | |
if (now != -1) { | |
first_read = now; | |
} | |
long sleep_to = first_read + (long)(rate * bytes_read); | |
long sleep_for = sleep_to - now; | |
if (sleep_for > 0) { | |
try { | |
Thread.sleep(sleep_for); | |
} catch (Exception e) { | |
throw new RuntimeException(e); | |
} | |
} | |
int result = bytes_read < size ? random.nextInt(256) : -1; | |
bytes_read++; | |
return result; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
👍