Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

generated mid already in use, cannot register Exchange #2298

Open
Josecaetanofaganello opened this issue Oct 29, 2024 · 6 comments
Open

generated mid already in use, cannot register Exchange #2298

Josecaetanofaganello opened this issue Oct 29, 2024 · 6 comments

Comments

@Josecaetanofaganello
Copy link

Josecaetanofaganello commented Oct 29, 2024

I have a Java/Scala application that uses Californium version 3.5.0, and I'm encountering an exception when I send a large volume of requests, around 400,000. I understand that MIDs have a limitation of 65,000, so I configured my service to send a maximum of 30,000 requests per batch, with each batch peaking at a 20-second interval. I also set the CoAP server and client EXCHANGE_LIFETIME to 2000 milliseconds.

This configuration helped avoid MID EXHAUSTED errors, but I'm still facing the error below. Do you have any suggestions for handling this situation? Is there a way I can better manage these MIDs?

2024-10-29 16:27:08,767 [:CoapEndpoint-UDP-0.0.0.0:0#1] DEBUG- o.e.c.c.n.s.ReliabilityLayer - Exchange[L16500068, 10.5.141.148:13000] send request
2024-10-29 16:27:08,767 [:CoapEndpoint-UDP-0.0.0.0:0#1] DEBUG- o.e.c.c.n.s.ReliabilityLayer - Exchange[L16500068, 10.5.141.148:13000] prepare retransmission for CON-POST MID= -1, Token=null, OptionSet={"Uri-Path":"AppOS", "Content-Format":"application/octet-stream"}, 08 01 10 FD EC CB A5 0C 18 01 2A 62 0A 14 33 2E 33 2E 31 2D 52 43 32 30 32 33 30 34 31 34 31 30..110 bytes
2024-10-29 16:27:08,768 [:CoapEndpoint-UDP-0.0.0.0:0#1] DEBUG- o.e.c.c.n.Exchange - Exchange[L16500068, 10.5.141.148:13000, complete]!
2024-10-29 16:27:08,768 [:CoapEndpoint-UDP-0.0.0.0:0#1] DEBUG- o.e.c.c.n.s.CleanupMessageObserver - failed, Exchange[L16500068, 10.5.141.148:13000, complete] request [MID=47473, null]
2024-10-29 16:27:08,768 [scala-execution-context-global-4014] ERROR- c.l.c.d.a.c.CoapHandler - ERROR SEND - Message to AppManager java.lang.IllegalArgumentException: generated mid [47473] already in use, cannot register Exchange[L16500068, 10.5.141.148:13000]
2024-10-29 16:27:08,768 [scala-execution-context-global-4014] INFO - c.l.c.d.a.c.CoapHandler - Message sent successfully.

@boaks
Copy link
Contributor

boaks commented Oct 30, 2024

generated mid [47473] already in use, cannot register Exchange[L16500068

If you use CON messages, it's important to supply valid MIDs, because the retransmission and deduplication is based on that. As long as messages may be in "flight", the MID must be "unique per peer". The error simply warns about a invalid MID ("already in use" is not unique).

Is there a way I can better manage these MIDs?

Why that happens exactly in your case, is not clear to me. Maybe some messages get lost and need retransmission but the EXCHANGE_LIFETIME of 2000 milliseconds doesn't work for that. Californium isn't designed for your use-case, nor is CoAP.

@Josecaetanofaganello
Copy link
Author

Currently, I’m only using NON messages, as I need to send them as fire-and-forget. However, when this error starts occurring, I notice that the messages stop arriving on the other side. I'm not sure if this is just a warning or if there’s another issue with the CoAP configuration.

@boaks
Copy link
Contributor

boaks commented Oct 30, 2024

Currently, I’m only using NON messages, as I need to send them as fire-and-forget.

Do you get this for Request or Response? Client or server?

@boaks
Copy link
Contributor

boaks commented Oct 30, 2024

another issue with the CoAP configuration.

No, it's an issue of misuse protocols ;-).

@Josecaetanofaganello
Copy link
Author

Josecaetanofaganello commented Oct 30, 2024

This setup is for requests made by the client side, where I am using the client as follows:

``

private def sendNonMessageAsync(deviceMessage: DeviceMessage)(implicit ec: ExecutionContext): Future[Unit] = {
    Future {
      try {

  
       val config = Configuration.createStandardWithoutFile
       config.set(CoapConfig.NON_LIFETIME, 2000, TimeUnit.MILLISECONDS)
       config.set(CoapConfig.EXCHANGE_LIFETIME, 2000, TimeUnit.MILLISECONDS)
        Configuration.setStandard(config)

        val client = new CoapClient(coapServerBase + CoapServerHost + ":" + NmpPort + "/" + npmResource)
        client.useNONs()
        client.setTimeout(100)

        val coapHandler = new CoapHandler() {
          override def onLoad(response: CoapResponse): Unit = {
            log.debug("Sent NON Message to (" + client.getURI + ")")
          }

          override def onError(): Unit = {
            log.error(s"ERROR SEND - NON Message to  ${deviceMessage.getMessageType}")
          }
        }

        log.debug(s"Inside sendNonMessage method for device id ${deviceMessage.getDeviceIdentifier}")
        client.post(coapHandler, deviceMessage.toByteArray, MediaTypeRegistry.APPLICATION_OCTET_STREAM)
      } catch {
        case e: Exception => log.error(s"ERROR SEND - NON Message ${e.getMessage}")
      }
    }
  }

``

@boaks
Copy link
Contributor

boaks commented Oct 31, 2024

This setup is for requests made by the client side

using NON messages, as I need to send them as fire-and-forget

Any request, if not using RFC 7967 No Server Response, will have a response. So "fire-and-forget" isn't really the case.

So, not sure, why do you use CoAP? Which functions do you want, if you disable quite a lot?
May it be easier for you to use Request, UdpDataSerializer and UDPConnector with your own logic (I never tested, if that works ;-) ).

And maybe, under load, the Request is canceled short before it's passed to the CoapStack (race condition).
So, if you like, please check, if adding !exchange.isComplete() in CoapEndpoint.sendRequest helps:

		final Exchange exchange = new Exchange(request, identity, Origin.LOCAL, executor);
		exchange.setEndpoint(this);
		exchange.execute(new Runnable() {

			@Override
			public void run() {
				if (!exchange.isComplete()) {
					coapstack.sendRequest(exchange, request);
				}
			}
		});

(edit: I don't think, this helps.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants