Skip to content

Conversation

@alexole01
Copy link
Contributor

JIRA:GRIF-316

@alexole01 alexole01 force-pushed the aole-test-gooddata-http-client branch from a65707a to 174f34c Compare June 17, 2025 14:22
zhabba
zhabba previously approved these changes Oct 31, 2025
Copy link

@zhabba zhabba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm but I'd like to have second pair of eyes here
@jiri-staroba would you please?

Copy link

@jiri-staroba jiri-staroba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are several concerns from a review in Cursor. Please verify them.

Critical issues

1. Potential race condition in token refresh synchronization

Location: GoodDataHttpClient.java:109-124

The token refresh synchronization may race. A thread can read tt after waiting, but the value might not be updated yet:

        synchronized (tokenRefreshMonitor) {
            if (tokenRefreshing) {
                while (tokenRefreshing) {
                    try {
                        tokenRefreshMonitor.wait();
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        throw new IOException("Interrupted while waiting for token refresh", e);
                    }
                }
                final ClassicHttpRequest retryRequest = cloneRequestWithNewTT(originalRequest, tt);
                return this.httpClient.execute(httpHost, retryRequest, context, response -> copyResponseEntity(response));
            } else {
                tokenRefreshing = true;
            }
        }

Issue: After notifyAll() at line 149, a waiting thread may proceed and read tt before it’s set. The tt assignment happens inside the writeLock block (lines 127-145), but waiting threads don’t re-check tt validity.

Recommendation: Add a validation check or ensure tt is set atomically before notifying waiters.

2. Lock contention: always using write lock

Location: GoodDataHttpClient.java:216

        // FIX: use only writeLock to avoid deadlock during handleResponse
        final Lock lock = rwLock.writeLock();

Impact: Using a write lock for all requests serializes reads, hurting throughput. The comment references a deadlock fix, but we should validate the deadlock scenario and consider alternatives.

Recommendation: Document why a read lock isn’t sufficient, or add a comment explaining the trade-off.

3. Unsupported HTTP methods in request cloning

Location: GoodDataHttpClient.java:163-183

    private ClassicHttpRequest cloneRequestWithNewTT(ClassicHttpRequest original, String newTT) {
        ClassicHttpRequest copy;
        // Clone basic types (extend if needed)
        switch (original.getMethod()) {
            case "GET":
                copy = new HttpGet(original.getRequestUri());
                break;
            case "DELETE":
                copy = new org.apache.hc.client5.http.classic.methods.HttpDelete(original.getRequestUri());
                break;
            default:
                throw new UnsupportedOperationException("Unsupported HTTP method: " + original.getMethod());
        }
        // Copy original headers
        for (Header header : original.getHeaders()) {
            copy.addHeader(header.getName(), header.getValue());
        }
        // Set the new TT
        copy.addHeader(TT_HEADER, newTT);
        return copy;
    }

Issue: Only GET and DELETE are supported; POST/PUT/PATCH fail. This blocks token refresh retries for those methods.

Recommendation: Support POST, PUT, and PATCH (clone request body as needed).

Major issues

4. Dead code and commented-out code

Location: GoodDataHttpClient.java:259, pom.xml:167,191

    public ClassicHttpResponse execute(HttpHost target, ClassicHttpRequest request) throws IOException {
       //  return httpClient.execute(target, request, (HttpContext) null, response -> response);
       return execute(target, request, null);
    }
                <!--    <skip>true</skip> -->

Remove commented-out code or justify its retention.

5. Missing null check in copyResponseEntity

Location: GoodDataHttpClient.java:287

        ContentType contentType = ContentType.parseLenient(response.getEntity().getContentType());

Issue: getContentType() may return null. parseLenient handles null, but calling it on a null value is risky.

Recommendation: Add explicit null handling or document the assumption.

6. Non-English comments in test code

Location: GoodDataHttpClientTest.java (multiple locations)

        // English comment: There should be exactly 3 httpClient.execute calls!

Issue: Comments like "English comment:" suggest non-English comments exist elsewhere.

Recommendation: Ensure all comments are in English and remove "English comment:" markers.

private final SSTRetrievalStrategy sstStrategy;
private final HttpHost authHost;
private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
private final Lock authLock = new ReentrantLock();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The field is not used anymore.

Copy link

@jiri-staroba jiri-staroba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we keeping the old version of the artifact 1.0.1-SNAPSHOT?

@alexole01 alexole01 force-pushed the aole-test-gooddata-http-client branch from 79fc7bc to f0366a0 Compare November 7, 2025 14:43
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

Successfully merging this pull request may close these issues.

4 participants