Akka http file streaming not writing bytes more than 'n' size from different clients - akka-stream

`Akka http 10.0.6;
max-content-length is set to 6000m`
I am using Akka file streaming to upload huge files( sent as octet-stream to my service ) to accept incoming bytes and write it to a file sink. This is what I observe from my experimentations.. My limited understand from reading the documents is the client should be able keep sending the data unless we tell explicitly from akka http for back pressure mechanisms.. Been searching online to understand this behavior, not able to get an understanding yet on this to explain the following behavior.. Is there something I am missing in the code? How can I debug more on this? Also, via scalatest, able to do it. If someone can throw more might on what’s the difference in behavior w.r.t scalatest and via curl/http clients.. Thanks
Through "curl", I can stream max of 1KB sized file. Anything more than this, it will just hang and this message is given after timeout no matter how long I wait(20 seconds, 5 mins, 10 mins, etc) "Sending an 2xx 'early' response before end of request was received... Note that the connection will be closed after this response. Also, many clients will not read early responses! Consider only issuing this response after the request data has been completely read!"
 
Through "Apache http client", max of 128KB sized file streaming happens. Anything more than this, it will hang and same message as in #1 from akka http service
 
Through "python client", max of ~26KB sized file streaming happens. Anything more than this, it will hang and same message as in #1 from akka http service
 
Through scalatest inside the service, was able to upload files like 200MB, 400MB and more also
Here’s the code..
`put {
withoutSizeLimit {
extractDataBytes { bytes =>
 
implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer()
// Tried system dispatcher also
implicit val executionContext = system.dispatchers.lookup("dispatcher")
val sink = FileIO.toPath(Paths.get("/file.out"))
val action = bytes.runWith(sink).map {
case ior if ior.wasSuccessful => {
complete(StatusCodes.OK, s"${ior.count} bytes written")
}
case ior => complete(StatusCodes.EnhanceYourCalm, ior.getError.toString)
}
Await.result(action, 300.seconds)
}
}
}`

Related

RxFrameNtf, TxFrameNtf and Ntf.data in unetpy

I am using Unetstack software along with Unetpy. I wish to retrieve transmit and recieve notifications when I run .py file which imports Unetpy python library. I followed this tutorial
I am successfully able to connect to the localhost and print values like phy.MTU and so on. When I transmit a packet I also receive a reply saying AGREE on the command prompt.output_of_my_script
my_script
Can you please help me in receiving Txframentf and rxframentf along with data payload.
I have made changes posted in bug reports suggested in this linkeven.
Please guide me on how to print notifications for rxframe and txframe.
Thank you``
Your script is fine until the last line:
print(phy << org_arl_unet_phy.TxFrameNtf())
Here you are trying to send a TxFrameNtf to the physical agent. This does not make sense, as it is the physical agent who sends you such a notification when a transmission is completed.
By the time you reach this line, you should have already received the notification as txntf as long as the transmission was completed within 5 seconds (timeout=5000). To print out the notification, all you need to do is:
print(txntf)
I just tested this against the 3-node-network.groovy sample. I am using unetpy-1.3b5 and fjagepy-1.4.2b3. Here's the modified code:
from unetpy import *
modem = UnetGateway('localhost', 1102)
phy = modem.agentForService(Services.PHYSICAL)
print(phy.MTU)
print(phy.basebandRate)
print(phy << org_arl_unet_phy.TxFrameReq(to=3, data=[1,2,3,4]))
txntf = modem.receive(timeout=5000)
print(txntf)
and the output:
16
4096
AGREE
TxFrameNtf:INFORM[type:1]
You can see that the TxFrameNtf is correctly received.
For reception, you need to subscribe to the agent's notifications and then receive a frame:
modem.subscribe(phy)
rxntf = modem.receive(org_arl_unet_phy.RxFrameNtf, timeout=5000)
print(rxntf)
Assuming you receive a frame within the 5 second timeout specified (in this example, on node 3), this should print out something like:
RxFrameNtf:INFORM[type:CONTROL from:1 to:3 protocol:0 rxTime:34587658 (4 bytes)]
You sent a datagram through some agent that supports the DATAGRAM service. There may be many agents that support this service (not just the physical layer). In any case, that datagram would be received on a different node, and so you wouldn't expect to receive DatagramNtf on the transmitting node.
The RangeReq should yield a RangeNtf if successful, but that might take more than the default receive timeout of 1 second, depending on how far node 2 is. So you might want to try a longer receive timeout to see if you get your notification.
To access the data from payload from the rxntf, you can try print(rxntf.data).

How to get partial results from Google App Engine's urlfetch?

When I'm using google.appengine.api.urlfetch.fetch (or the asynchronous variant with make_rpc) to fetch a URL that steadily streams data, after a while I will get a google.appengine.api.urlfetch_errors.DeadlineExceededError as expected. Since it is a stream that I want to sample, setting the deadline to a higher value can't ever help, unless the stream finishes (which I do not expect to happen).
It seems there is no possibility of getting the partially downloaded result. At least the API doesn't offer anything. Is it possible to
either request the downloaded part
or only ask for a certain amount of data (since I can estimate the stream's rate) to be downloaded?
[Clarification: Since it is a stream, requests with a Range header will be answered with 200 OK and not 206 Partial Content.]
In your call to urlfetch.fetch, you can set HTTP headers. The Range header is how you specify a partial-download request in HTTP:
resp = urlfetch.fetch(
url=whatever,
headers={'Range': 'bytes=100-199'})
if those are the 100 bytes you want. The HTTP status code you get should be 206 for such a partial download, etc (none of that's GAE-specific). See e.g http://en.wikipedia.org/wiki/Byte_serving for details.

GAE "The API call urlfetch.Fetch() required more quota than is available" when resumable upload Video files

my GAE application reads files from Drive by Drive API into a FileStream, and then the FileStream is uploaded into Youtube by Youtube API v3 with "resumable upload". When the file size gets larger (e.g. 60M ), the Youtube API returns this error "The API call urlfetch.Fetch() required more quota than is available"
I also have tried with "direct upload" for uploading 60M size video file, then error message would be "java.lang.OutOfMemory: Java heap space at com.google.protobuf.ByteString.copyFrom (ByteString.java:178)".
Here is the brief version of my code:
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(YouTubeScopes.YOUTUBE)
.setServiceAccountPrivateKeyFromP12File(new File(P12))
.setServiceAccountUser(account).build();
YouTube service = new YouTube.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential).setApplicationName("VSP").build();
Video videoObjectDefiningMetadata = new Video();
VideoSnippet snippet = new VideoSnippet();
snippet.setTitle(title);
videoObjectDefiningMetadata.setSnippet(snippet);
InputStreamContent mediaContent = new InputStreamContent(VIDEO_FILE_FORMAT, new BufferedInputStream(filestream));
mediaContent.setLength(filesize);
YouTube.Videos.Insert videoInsert = service.videos().insert("snippet,statistics,status", videoObjectDefiningMetadata, mediaContent);
MediaHttpUploader uploader = videoInsert.getMediaHttpUploader();
uploader.setDirectUploadEnabled(false);
uploader.setChunkSize(7864320);
Video returnedVideo = videoInsert.execute();
error message "The API call urlfetch.Fetch() required more quota than is available" comes at last line of the code. sometimes the uploading is done successfully with the error message, sometimes not, by setting the ChunkSize differently.
I couldn't find any useful information about this error message. But my guess is that GAE application can only send certain mount of requests during certain mount of time. Since "resumable upload" is breaking the filestream into chunks, and send them in a sequence of requests, it reaches the limit easily. if my guess is right, what is the limit? and how do i solve this problem? if my guess is wrong, where do you think the problem is?
Thanks
Thanks guys!
Here is the limit for incoming & outgoing bandwidth for URL Fetch in GAE:
https://developers.google.com/appengine/docs/quotas
By default, the limit is 22M/min, with bill enabled, the limit becomes 740M/min. so with 22M/min limit, a GAE task queue can upload about 220M video files to Youtube (22M * 10min)
But this leads to the problem of using the upper code
Video returnedVideo = videoInsert.execute();
, becoz we cannot control the how many chunks are sent every minute in that code. The solution which i did, is to follow the description in the following link to handle each of the requests by myself. https://developers.google.com/youtube/v3/guides/using_resumable_upload_protocol
in this way, we can control the size of stream which could be sent each minute.

G-WAN persist request data in handler

Solution:
int session = (int)get_env(argv, SESSION_ID); to get identifier unique to connection
US_VHOST_DATA (vhost) or US_HANDLER_DATA (listener) or US_SERVER_DATA (server) for data persistent > current connection
Missing pieces:
either persistent data for connection only
or some way to execute code when current connection is closed by client (econnreset etc.) or server (e.g. kalive_tmo reached)
This should be solvable as soon as a new HDL_BEFORE_CLOSE state for handlers is added, which makes this question answered for me.
Original Question:
Is it possible in a G-WAN handler to store information persistent to a request/connection (don't really know if "request" applies here)?
To better illustrate what I mean, this is what I got now:
Client (browser, javascript) sends websocket handshake
Handler starts, gets into:
HDL_AFTER_ACCEPT - here i call gc_init for US_REQUEST_DATA, and get no error
HDL_AFTER_READ - here i check for US_REQUEST_DATA which is not yet set, so I do websocket handshake and gc_malloc + set US_REQUEST_DATA, increase KALIVE_TMO, and then return 2 to send data
Client sees websocket connection as being established, so I (manually triggered some seconds afterwards) send a message
Handler goes to HDL_AFTER_READ again, BUT US_REQUEST_DATA is not set
What I've also tried:
returning 1 instead of 2 in HDL_AFTER_READ -> client gets 404 and handshake does not work
At the moment I'm only using US_REQUEST_DATA to identify if websocket connection is already established and next incoming data should be in websocket message format, so if there is a different (maybe better?) solution, I'm open to that as well of course.
Thanks!
Edit: Added clarification about request/connection
I am not sure why US_REQUEST_DATA does not seem to keep your allocated block of memory.
Can you try the persistence.c example to see if it works as expected for you?
Other than G-WAN persistent pointers, you can use OS services like the Linux shared memory API, etc.
But the G-WAN API should work fine once you copy & paste the example above.
Other values have different scopes:
US_VHOST_DATA (scope:vhost)
US_HANDLER_DATA (scope:listener)
US_SERVER_DATA (scope:server)
Use the session ID below which is unique to each CONNECTION:
int session = (int)get_env(argv, SESSION_ID);

Writing a GSM modem driver?

I've been working on an application which uses a GSM modem for one of two things; check its status using the built in HTTP stack by sending a GET request to the server, or sending data to the server (using UDP). I have tried several different methods to keep this as reliable as possible, and I'm finally ready to ask for help.
My application is written for the SIMCOM908 module and the PIC18 platform (I'm using a PIC18 Explorer for development).
So the problem is sometimes the modem is busy doing something, and misses a command. As a human, I would see that and just resend the command. Adding a facility for my MCU to timeout and resend isn't an issue.
What is an issue is that the modem sends unsolicited responses after different events. When the modem changes registration status (with the cell tower) it would respond with +CGREG: 1, ... or when the GPS is ready GPS Ready. These responses can happen at any time, including in the middle of a command (like creating an IP connection).
This is a problem, because I haven't thought of a way to deal with this. My application needs to send a command (to connect to the server for example, AT+CIPSTART="UDP","example.com",5000) This command will response with 'OK', and then when the command has finished 'CONNECT OK'. However, I need to be able to react to the many other possible responses, and I haven't figured out a way of doing this. What do I need to do with my code to; wait for a response from the modem, check the response, perform an action based on that response?
I am code limited (being an 8-bit microcontroller!) and would like the keep repetition to a minimum. How can I write a response function that will take a response from the GSM module (solicited or now) and then let the rest of my program know what is happening?
Ideally, I'd like to do something with those responses. Like keep an internal state (when I hear GPS Ready, I know I can power the GPS etc.
Maybe there are some things I should think about, or maybe there's an open source project that already solves this problem?
Here's what I have so far:
/* Command responses */
enum {
// Common
OK = 0,
ERROR,
TIMEOUT,
OTHER,
// CGREG
NOT_REGISTERED,
// CGATT
NOT_ATTACHED,
// Network Status
NO_NETWORK,
// GPRS status
NO_ADDRESS,
// HTTP ACTION
NETWORK_ERROR,
// IP Stack State
IP_INITIAL,
IP_STATUS,
IP_CONFIG,
UDP_CLOSING,
UDP_CLOSED,
UDP_CONNECTING
} gsmResponse;
int gsm_sendCommand(const char * cmd) {
unsigned long timeout = timer_getCurrentTime() + 5000;
uart_clearb(GSM_UART); // Clear the input buffer
uart_puts(GSM_UART, cmd); // Send the command to the module
while (strstr(bf2, "\r") == NULL) { // Keep waiting for a response from the module
if (timeout < timer_getCurrentTime()) { // Check we haven't timed out yet
printf("Command timed out: %s\r\n", cmd);
return TIMEOUT;
}
}
timer_delay(100); // Let the rest of the response be received.
return OK;
}
int gsm_simpleCommand(const char * cmd) {
if (gsm_sendCommand(cmd) == TIMEOUT)
return TIMEOUT;
// Getting an ERROR response is quick, so if there is a response, this will be there
if (strstr(bf2, "ERROR") != NULL)
return ERROR;
// Sometimes the OK (meaning the command ran) can take a while
// As long as there wasn't an error, we can wait for the OK
while (strstr(bf2, "OK") == NULL);
return OK;
}
A simple command is any AT command that is specifically looking for OK or ERROR in response. Something like AT. However, I also use it for more advanced commands like AT+CPIN? because it means I will have captured the whole response, and can further search for the +CPIN: READY. However, none of this actually response to the unsolicited responses. In fact, the gsm_sendCommand() function will return early when the unsolicited response is received.
What a good way to manage complex, occasionally unsolicited, status messages like this? Please take note that this application is written in C, and runs on an 8bit microcontroller!
Having to handle both unsolicited messages as well as responses to requests in the same data stream is difficult since you will need to demultiplex the incoming stream and dispatch the results to the appropriate handler. It's a bit like an interrupt handler in that you have to drop what you were doing and handle this other bit of information which you were not necessarily expecting.
Some modules have a secondary serial port which can also be used for messages. If this is possible you could have unsolicited messages only appear on a single serial port while the main port is for your AT commands. This may not be possible, and some GSM modules will not support the complete command set on a secondary port.
Perhaps a better approach is to just disable unsolicited messages. Most commands all the state to be requested. eg While waiting for registration, instead of waiting for an unsolicited registration message to appear, simply poll the module for the current registration state. This allows you to always be in control, and you only have to handle the responses for the command just sent. If you're waiting for multiple events you can poll in a loop for each item in turn. This will generally make the code simpler as you only have to handle a single response at a time. The downside is that your response times are limited by your polling rate.
If you're set on continuing with the unsolicited message approach, I'd suggest implementing a small queue for unsolicited messages. While waiting for responses to a command, if the response does not match the command, just push the response on a queue. Then, when you've either received a response to your AT command or timed out you can process the unsolicited message queue afterwards.

Resources