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

Categories API not working #37

Closed
Ligerx opened this issue May 12, 2019 · 3 comments
Closed

Categories API not working #37

Ligerx opened this issue May 12, 2019 · 3 comments

Comments

@Ligerx
Copy link

Ligerx commented May 12, 2019

Tried to add manga to categories in v3 returned a 501 not implemented error, so here I am trying to use the v2 api.

Here's a list of categories I made

{
    "data": [
        ...
        {
            "id": 4,
            "name": "Blah 2",
            "order": 2,
            "flags": 0,
            "manga": []
        },
        ...
    ],
    "success": true
}

Calling GET on http://localhost:4567/api/v2/categories/4/name returns

{
    "data": [
        {
            "id": 4,
            "name": "Blah 2"
        }
    ],
    "success": true
}

but I can't figure out any way to get a POST to work. I tried multiple combinations of JSON data and nothing worked. Here's one of the errors that the server is giving.

[qtp1154610887-50] ERROR xyz.nulldev.ts.api.http.TachiWebRoute - Route handler failure (error ID: 03f10d52-769b-4137-afef-e4a7722fee34)!
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `xyz.nulldev.ts.api.v2.http.categories.CategoryName[]` out of START_OBJECT token
 at [Source: (String)"{
    "name": "change this"
}"; line: 1, column: 1]
	at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
	at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1343)
	at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1139)
	at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1093)
	at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.handleNonArray(ObjectArrayDeserializer.java:330)
	at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:175)
	at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:21)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3004)
	at io.javalin.translator.json.JavalinJsonPlugin$jsonToObjectMapper$1.map(JavalinJsonPlugin.kt:28)
	at xyz.nulldev.ts.api.v2.http.jvcompat.JavalinCompatKt.bodyAsClass(JavalinCompat.kt:39)
	at xyz.nulldev.ts.api.v2.http.categories.CategoriesController.setName(CategoriesController.kt:155)
	at xyz.nulldev.ts.api.http.HttpAPI$start$26.invoke(HttpAPI.kt:181)
	at xyz.nulldev.ts.api.http.HttpAPI$start$26.invoke(HttpAPI.kt:60)
	at xyz.nulldev.ts.api.v2.http.jvcompat.JavalinShim.handleReq(JavalinShim.kt:9)
	at xyz.nulldev.ts.api.http.TachiWebRoute.handle(TachiWebRoute.kt:75)
	at spark.RouteImpl$1.handle(RouteImpl.java:61)
	at spark.http.matching.Routes.execute(Routes.java:61)
	at spark.http.matching.MatcherFilter.doFilter(MatcherFilter.java:130)
	at spark.embeddedserver.jetty.JettyHandler.doHandle(JettyHandler.java:50)
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1568)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
	at org.eclipse.jetty.server.Server.handle(Server.java:531)
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:352)
	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260)
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:281)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102)
	at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:319)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:175)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:133)
	at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:366)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:754)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:672)
	at java.lang.Thread.run(Thread.java:748)

@null-dev
Copy link
Contributor

The v3 endpoint should be fixed now.

I think the reason v2 was behaving strangely for you is because all of the v2 endpoints actually expect batch operations. E.g. take a look at the API response produced in your example above when you this this endpoint: http://localhost:4567/api/v2/categories/4/name. Notice how the data field in the response is actually an array. This is because you can actually query for the names of multiple categories at the same time by doing something like this: GET http://localhost:4567/api/v2/categories/4,5/name.

This is actually the whole reason I started to move away from v2. The every endpoint supports batch operations was cool but had several critical flaws:

  • Most calls to the API only ever touch one object. So even though every endpoint had batch support, it was very rarely used.
  • Implementing an API where every endpoint must support batch operations is really hard and messy.
  • The server must talk to the Tachiyomi code which usually doesn't support batch operations (even though the database does). The server architecture looks like this: TachiWeb <---> Tachiyomi <---> Database. So what often happened was when the server received a batch operation, it would actually just perform the operations one-by-one instead. You might think this wouldn't be a problem but performing hundreds of database queries instead of one big query is actually really, really slow and ended up killing performance.

So yeah, that's why I dropped v2 lol.

@Ligerx
Copy link
Author

Ligerx commented Jun 22, 2019

@null-dev
Would it be possible to add an API call or enhance the existing list all categories API?
It would be nice to get a list of mangaIds that aren't in any category (default) instead of manually figuring it out the front end.

@null-dev
Copy link
Contributor

null-dev commented Jun 22, 2019

@Ligerx Sure, I'll make /api/v3/categories (getCategories) return all the categories + a dummy category that:

  • has an ID of -1
  • has an order of -1 (the "default" category should always be displayed prior to all other categories)
  • has a name of Default
  • contains all the manga that are not in categories

Note that the "default" category will be just a dummy category. It doesn't actually exist so you won't be able to reorder/rename it using the API.

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

No branches or pull requests

2 participants