appwrite / templates

Templates for Appwrite Functions ⚡️🌩️
https://appwrite.io
MIT License
103 stars 80 forks source link

🚀 Feature: Add Sync with Meilisearch for Java #191

Closed gewenyu99 closed 8 months ago

gewenyu99 commented 9 months ago

Appwrite Functions allow you to extend and customize your Appwrite server functionality by executing your custom code. 🤩 You can learn more at our official Appwrite Functions docs.

Your task is to implement the Sync with Meilisearch function in Java. You can look at the existing Appwrite Functions Templates in another coding language.

Your function should behave and be implemented similarly to existing Sync with Meilisearch Node.js template.

Tasks summary:

If you need any help, contact us on our Discord server.

Are you ready to work on this issue? 🤔 Let us know, and we will assign it to you 😊

Happy Appwriting!

GLADI8R commented 9 months ago

Hi, I would like to work on this issue. Can you assign it to me?

tessamero commented 9 months ago

hi @GLADI8R , you've been assigned to the issue. You may start working on it. :-) Please keep us updated every 3 days so we know you are still working on it, so the issue doesn't get reassigned :)

happy coding 😃

Bijit-Mondal commented 9 months ago

If it is not done, please assign me to this

Haimantika commented 9 months ago

If it is not done, please assign me to this

Hi, we assign issues on first-come first-serve basis, if we do not have an update from Danish, we will assign it to you!

GLADI8R commented 9 months ago

I'm having difficulty in setting up the project environment. If anyone can help out with setting up and running the starter code. I'm using Java 17, Gradle 8.3, IntelliJ IDE

GLADI8R commented 9 months ago

Hi, I'm still working on this issue. Update till now: understood the appwrite console, CLI, and the nodejs code. Stuck setting up the Java-17 environment in CLI. Included runtime of java-17.0 in .env of appwrite but java option is not visible during appwrite init function.

GLADI8R commented 9 months ago

Update till now: Working on the code right now and resolving the build errors.

FelixFelicis555 commented 8 months ago

Assign the issue to me if the issue didn't get sorted or either of them didn't respond

GLADI8R commented 8 months ago

Hi @FelixFelicis555, I'm still working on this.

GLADI8R commented 8 months ago

Hi @Haimantika @gewenyu99, I've been stuck on getting documents list. Have posted this on support channel on discord, but no replies from anyone on how to fix it. What should I do?

gewenyu99 commented 8 months ago

@GLADI8R What's the issue with document list?

GLADI8R commented 8 months ago

I followed the kotlin sdk docs and on using the function databases.listDocuments({params}), the error says no such function as listDocuments(). Am not able to access the class functions even though the Databases and Client instances are working fine Using kotlin-sdk v4.0.0 on self-hosted appwrite cli v4.1.0

gewenyu99 commented 8 months ago

Can I see your code?

GLADI8R commented 8 months ago

import com.meilisearch.sdk.Config;
import com.meilisearch.sdk.Index;

import io.openruntimes.java.RuntimeContext;
import io.openruntimes.java.RuntimeOutput;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Arrays;

import java.nio.file.Files;
import java.nio.file.Path;

import io.appwrite.Client;
import io.appwrite.services.Databases;
import io.appwrite.Query;
import io.appwrite.models.DocumentList;
import io.appwrite.models.Document;

public class Main {
    String[] envStrings = {
            "APPWRITE_API_KEY",
            "APPWRITE_DATABASE_ID",
            "APPWRITE_COLLECTION_ID",
            "MEILISEARCH_ENDPOINT",
            "MEILISEARCH_INDEX_NAME",
            "MEILISEARCH_ADMIN_API_KEY",
            "MEILISEARCH_SEARCH_API_KEY"
    };
    List<String> envList = Arrays.asList(envStrings);

    final String regex = "\\{\\{([^\\}]+)\\}\\}";

    private void throwIfMissing(Map<String, String> env) throws Exception {
        List<String> missing = new ArrayList<>();

        for(String e: envList) {
            if (!env.containsKey(e) || env.get(e).isEmpty()) {
                missing.add(e);
            }
        }

        if (missing.size() > 0) {
            throw new Exception("Missing values in .env");
        }
    }

    private String interpolate(String template, Map<String, String> vars) {
        for(String key: vars.keySet()) {
            template = template.replaceAll("\\{\\{([^\\}]+)\\}\\}", vars.get(key));
        }

        return template;
    }

    private String getStaticFile(String filename) {
        return Files.readString(Path.of(filename));
    }

    /**
     * @param context
     * @return
     * @throws Exception
     */
    public RuntimeOutput main(RuntimeContext context) throws Exception {

        throwIfMissing(System.getenv());

        if (context.getReq().getMethod().equals("GET")) {
            Map<String, String> conf = new HashMap<String, String> ();
            conf.put("MEILISEARCH_ENDPOINT", System.getenv("MEILISEARCH_ENDPOINT"));
            conf.put("MEILISEARCH_INDEX_NAME", System.getenv("MEILISEARCH_INDEX_NAME"));
            conf.put("MEILISEARCH_SEARCH_API_KEY", System.getenv("MEILISEARCH_SEARCH_API_KEY"));

            String html = interpolate(getStaticFile("index.html"), conf);

            Map<String, String> headers = new HashMap<String, String> ();
            headers.put("Content-Type", "text/html; charset=utf-8");

            return context.getRes().send(html, 200, headers);
        }

        Client client = new Client();
        client
                .setEndpoint(System.getenv("APPWRITE_ENDPOINT").toString())
                .setProject(System.getenv("APPWRITE_FUNCTION_PROJECT_ID").toString())
                .setKey(System.getenv("APPWRITE_API_KEY").toString());

        Databases databases = new Databases(client);

        // meilisearch client
        Config meilisearchConfig = new Config(
                System.getenv("MEILISEARCH_ENDPOINT").toString(),
                System.getenv("MEILISEARCH_ADMIN_API_KEY").toString()
        );
        com.meilisearch.sdk.Client meilisearch = new com.meilisearch.sdk.Client(meilisearchConfig);

        Index index = meilisearch.index(System.getenv("MEILISEARCH_INDEX_NAME"));

        String cursor = null;

        do {
            List<String> queries = new ArrayList<String>();

            if(cursor != null && queries.size()<100) {
                queries.add(cursor);
            }

            List<Document<Map<String, Object>>> documents = databases.listDocuments(
                    System.getenv("APPWRITE_DATABASE_ID").toString(),
                    System.getenv("APPWRITE_COLLECTION_ID").toString(),
                    queries
            ).toMap().get("documents");

            if(documents.size() > 0) {
                cursor = documents.get(documents.size() - 1).id.toString();
            } else {
                context.log("No more documents found.");
                cursor = null;
                break;
            }

            context.log("Syncing chunk of " + documents.size() + " documents ...");
            index.addDocuments(documents.toString(), "id");

        } while(cursor != null);

        return context.getRes().send("Sync finished", 200);
    }
}
gewenyu99 commented 8 months ago

I can't reproduce this problem @GLADI8R, how are you deploying the function, what are your build commands?

GLADI8R commented 8 months ago

I'm using self-hosted appwrite cli. I did appwrite deploy function and the build logs show that no method listDocuments. The parameters and imports are same as mentioned in sdk-for-kotlin.

gewenyu99 commented 8 months ago

@GLADI8R what build commands did you configure to install Appwrite as a dependency in the function?

GLADI8R commented 8 months ago

generated the starter function using appwrite init project then the function. Inside deps.gradle, I have:

dependencies {
    implementation 'io.appwrite:sdk-for-kotlin:4.0.0'
    implementation 'com.meilisearch.sdk:meilisearch-java:0.11.2'
}
gewenyu99 commented 8 months ago

generated the starter function using appwrite init project then the function. Inside deps.gradle, I have:

dependencies {
    implementation 'io.appwrite:sdk-for-kotlin:4.0.0'
    implementation 'com.meilisearch.sdk:meilisearch-java:0.11.2'
}

Can I see the build commands you configured in your Appwrite Console?

gewenyu99 commented 8 months ago
Screenshot 2023-10-11 at 3 46 47 PM
GLADI8R commented 8 months ago

No commands are displayed and I haven't used any build commands. Just deployed the function...

gewenyu99 commented 8 months ago

@GLADI8R In that case, no dependencies, including the Appwrite SDK is installed. Remember to run a install command for which ever dependency manager you're using!

GLADI8R commented 8 months ago

I don't think I need any build commands because the dependencies are already in deps.gradle file and on deploying the function, gradle runs perfectly. The only issue is that the relevant class methods are not recognized. method signature here: https://github.com/appwrite/sdk-for-kotlin/blob/main/src/main/kotlin/io/appwrite/services/Databases.kt

loks0n commented 8 months ago

No commands are displayed and I haven't used any build commands. Just deployed the function...

What version of Appwrite are you using?

Does the starter function work for you?

I don't think I need any build commands because the dependencies are already in deps.gradle file and on deploying the function, gradle runs perfectly. The only issue is that the relevant class methods are not recognized. method signature here: https://github.com/appwrite/sdk-for-kotlin/blob/main/src/main/kotlin/io/appwrite/services/Databases.kt

What's wrong with the method signature?

GLADI8R commented 8 months ago

Using appwrite v1.4.3. I made changes in the starter template generated in appwrite init function. When using databases.listDocuments(), logs show method not applicable.

image

Haimantika commented 8 months ago

Using appwrite v1.4.3. I made changes in the starter template generated in appwrite init function. When using databases.listDocuments(), logs show method not applicable.

image

Hi, if you are still stuck in this, would request you to open a support thread in our Discord server

loks0n commented 8 months ago

Did you find a solution for this?

tessamero commented 8 months ago

Closing issue due to inactivity and hacktoberfest being over, thank you for taking the time to be part of hacktoberfest this year :)