How to use Ignite Cache TextQuery in .Net Application - c#

I am using Apache Ignite v2.7.6.And I have a .Net core ClientServer Ignite App.
I am trying to read/search text from the Person Model field Payload marked with QueryTextField.
TextQuery Ignite Docs.
Person Model:
public class Person: IConstructionCacheStore
{
[QueryTextField]
public string Payload { get; set; }
}
Code:
using (IIgniteClient client = Ignition.StartClient(this._igniteClientConfiguration))
{
//get cache config
var cache = client.GetCache<string, IConstructionCacheStore>(cacheName);
try
{
// Query for all people with "Master Degree" in their resumes.
var cursor = cache.Query(new TextQuery("Person", "Master Degree"));//Error
// Iterate over results. Using 'foreach' loop will close the cursor automatically.
foreach (var cacheEntry in cursor)
Console.WriteLine(cacheEntry.Value);
}
catch (Exception ex)
{
throw;
}
}
But I am getting a compile-time error at cache.Query(new TextQuery("Person", "Master Degree"));
like
Error CS1503 Argument 1: cannot convert from
'Apache.Ignite.Core.Cache.Query.TextQuery' to
'Apache.Ignite.Core.Cache.Query.ScanQuery<string,
ConstructionModels.IConstructionCacheStore>'
is TextQuery support in .Net?
How to solve above error?
Thanks.

TextQuery is not supported in Ignite thin clients:
Use thick client instead (.NET thick client supports TextQuery)
Use Services or Compute as a workaround (wrap TextQuery call in a Service or Compute Task, use thin client to call the service or the task)

Related

.NET Core GetFromJsonAsync exits with no error or debugging information

I am trying to debug a request by GetFromJsonAsync which is supposed to fetch data from a Flask API and convert to JSON within a .NET Core cli app.
The issue I am having however is that after performing the request the cli app simply exits with no error. I have tried implementing try/catch block but nothing shows up there.
the Flask endpoint builds jsonifies a number of uuids and messages from Postgres and returns them to the client.
As GetFromJsonAsync is asynchronous I have tried making the Flask endpoint likewise but that has not seemed to help at all. The latter works fine and has been validated with curl.
I know the call executes as I can see it in my web server logs.
A similar call which simply returns plain javascript object {"foo": "bar"} works fine which is why I think this could by an async issue but I cannot see any errors etc to troubleshoot. I have placed a breakpoint on the foreach after the call but this is never hit.
What am I missing here?
public static async void GetMessages()
{
ConfigureHeaders();
try
{
var client = Client;
var res = await Client.GetFromJsonAsync<Received>(Url + "/api/chat/message"); // stops here
foreach (var c in res!.messages) // breakpoint here is never hit
Console.WriteLine(c);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
public class Received
{
public Dictionary<string,string> messages { get; set; }
}
Flask
#message.get("/api/chat/message")
#csrf.exempt
async def get_messages():
new_msgs = {}
msgs = await get_unreplied() # DB gets called from another function here
try:
for m in msgs:
new_msgs[m.id] = m.message
if len(new_msgs) != 0:
return jsonify(new_msgs)
else:
return jsonify("no messages")
except Exception as e:
print(str(e))
This returns...
{
"id_foo1": "message_bar1",
"id_foo2": "message_bar2"
}
Best guess: your Main function is not awaiting the call to GetMessages
public async Task<int> Main(string []args)
{
await GetMessages();
}

Azure storage 'Lease' - correct exception approach

I am developing NET Core web app and I am using blob to store some objects what could be modified during request. I had to prevent multiple paralel access to one object so I add 'lease' into my storage integration.
In prctice when I receive request, one object is fetched from blob with lease for some period. On the end of request this object is updated in storage and lease is removed - pretty simple.
But what is correct exception handling?
I am faicing agains the problem when some exception occured in the middle of request, lease is not released. I tried to implement release into dispose (in some class where I control fetching and leasing from blob). But this is not executed when unhandled exception is thrown.
Add try/catch/finally seems not clean for me. My question is do you know some best common approach how release lease on the end request? Thank you
Per your description, I write a simple demo for you about lease and break lease, just try the code below:
using System;
using Azure.Storage.Blobs;
using Microsoft.AspNetCore.Mvc;
using Azure.Storage.Blobs.Specialized;
using System.Threading;
namespace getSasTest.Controllers
{
[ApiController]
[Route("[controller]")]
public class editBlob : ControllerBase
{
[HttpGet]
public string get()
{
var connstr = "";
var container = "";
var blob = "";
var blobClient = new BlobContainerClient(connstr,container).GetBlobClient(blob);
var leaseClient = new BlobLeaseClient(blobClient);
try
{
//auto break lease after 15s
var duration = new TimeSpan(0, 0, 15);
leaseClient.Acquire(duration, null);
}
//if some error occurs, request ends here
catch (Azure.RequestFailedException e)
{
if (e.ErrorCode.Equals("LeaseAlreadyPresent"))
{
return "Blob is under process,it will take some time,please try again later";
}
else
{
return "some other Azure request errors:"+ e.Message;
}
}
catch (Exception e) {
return "some other errors:" + e.Message;
}
//mock time consumption to process blob
Thread.Sleep(10000);
//break relase first if process finishs in 15s.
leaseClient.Break();
return "Done";
}
}
}
So, based on your requirements, can't you authorize a party/cron/event (register event/ttl handlers?) to break a lease when some weirdness (whatever that means for you) is detected. It looks like you are really worried on the "pattern" over correctness?.
This should complement the correctness.
In practice, an exception handling strategy should lead to sufficient actionable information.
For some, that means:
E -> E - 1 (digest or no digest) -> E - 2 (digest or no digest) ..
such that:
E - n: Exception, at a certain level of nesting
digest: would you propagate this or digest and move forward?
Breaking the lease (essentially correctness of program) should not mean you hamper your version of the elegance.
Every service is usually a pair of services:
service itself
service clean-up handler 1 through n
service edge case handler 1 through n
primer for service
so on...

Neo4j Driver for .NET Readonly mode not working

I have problem with Neo4j Driver for .NET. To execute query, i use session with ReadOnly mode and Read transaction, but still i can modify graph via query like: Match (n) where Id(n) = 123 set n.foo = 33 return n; My code:
using (var session = Driver.Session(AccessMode.Read))
{
session.ReadTransaction(tx =>
{
try
{
var queryResult = tx.Run(job);
}
catch (Exception ex)
{
errorMessage = ex.Message;
}
});
}
Why is possible? How resolve this problem?
The AccessMode.Read define the type of the session, and this is used only when you are on a cluster mode, to perform session's transactions on a replica server and not on a core server.
It doesn't not tell that your session is a readonly one.
To have a pure read only access, you need to connect to Neo4j with a read only user.

If another request is running a method wait until finish

I'm developing an ASP.NET Web API application with C#, .NET Framework 4.7 and MongoDb.
I have this method:
[HttpPut]
[Route("api/Public/SendCommissioning/{serial}/{withChildren}")]
public HttpResponseMessage SendCommissioning(string serial, bool withChildren)
{
string errorMsg = "Cannot set commissioning.";
HttpResponseMessage response = null;
bool serverFound = true;
try
{
[...]
// Mongo
MongoHelper mgHelper = new MongoHelper();
mgHelper.InsertCommissioning(serial, withChildren);
}
catch (Exception ex)
{
_log.Error(ex.Message);
response = Request.CreateResponse(HttpStatusCode.InternalServerError);
response.ReasonPhrase = errorMsg;
}
return response;
}
Sometimes this method is called very quickly and I get an error here:
// Mongo
MongoHelper mgHelper = new MongoHelper();
mgHelper.InsertCommissioning(serial, withChildren);
Here I'm inserting the serials I received in order, and sometimes I get an error with a duplicated key in MongoDb:
I have a method to get the latest id used in Mongo (the primary key). And two requests get the same id, so when I try to insert it on Mongo I get an invalid key exception.
I thought to use a queue to store the serials and then consume them in the same order that I have received them. But I think I will get the same error when I try to store the serial in MongoDb.
Maybe if I can set a method that if it is running, I have to wait to run it, it will works. This method will have the part of insert the serials into Mongo.
How can I do that? A method that if it is running you can't run it in another Web Api request.
Or, do you know a better option?
By the way, I can't block this method. Maybe I need to run a thread with this synchronized part.

OData Simple Client: Linked collection for type [Type] not found

I have xamarin forms application. I use odata simple client to manipulate app database.
I am trying to add data to many-to-many tables.
This is my first entity
public class Genre : BaseGenre
{
List<User> Users { get; set; }
}
And my other one
public class User : BaseUser
{
List<Genre> Genres { get; set; }
}
And this the function I am trying to link them
public async void AddGenresAsnyc(User u, List<Genre> Genres)
{
u.Genres = Genres;
try {
//await client.For<User> (CollectionName).Key(u).LinkEntryAsync(us => us.Genres, Genres);
await client.For<User> (CollectionName).Key(u.id).Set(u).UpdateEntriesAsync();
} catch (Exception e) {
Exception ex = e;
}
}
The first one, linkentryasync throws the exception
Number of parameter does not match expected count.
And the second one throws
Linked collection for type [Genre] not found
Any help would be great. I am stuck at work. Thanks in advance.
One immediate thing that you need to change is make properties Genre.Users and User.Genres public. Simple.OData.Client uses reflection to assign property values and is not capable of assigning values for private properties/fields. I tested your code with the schema you sent me and as long as the properties were public, the request went through.
Regarding the next example (using LinkEntryAsync), if you want to update links in a single call, you should use UpdateEntryAsync, because LinkEntryAsync does it for a single link. So either use:
var user = await client.For<User>("ApiUser").Key(1).FindEntryAsync();
user.Genres = genres;
await client.For<User>("ApiUser").Key(user).Set(user).UpdateEntryAsync();
or
foreach (var genre in genres)
{
await client.For<User>("ApiUser").Key(user).LinkEntryAsync(genre);
}
The first operation could have been written in a more efficient way:
await client.For<User>("ApiUser").Key(1).Set(new {Genres = genres}).UpdateEntryAsync();
That will generate HTTP PATCH instead of PUT with only Genres updated, but it looks like your OData service requires all mandatory properties to be sent on the entity being updated, so this won't work.
Last but not least: get the latest version (4.9.1) of Simple.OData.Client. It has a fix that is important for your scenario.
UPDATE. I tested your OData service, and it doesn't seem to have a proper support for addressing links. For example, if I test sample OData service, I can execute requests like http://services.odata.org/V4/OData/%28S%28ygi3rwu514y0a4ooybn3d1gc%29%29/OData.svc/Products%284002%29/Categories/$ref (note $ref segment that addresses Caterogories link so this URI can be used to post link updates). But if I execute request http://{your_service_uri}/ApiUsers%281%29/Genres/$ref then I get an error "No HTTP resource was found that matches the request URI 'http://partymag.azurewebsites.net/ApiUsers(1)/Genres/$ref'." As long as this link doesn't work on a server side you won't be able to use LinkEntryAsync or UnlinkEntryAsync but you can still use UpdateEntryAsync as I showed above.
UPDATE2. The version that uses UpdateEntryAsync executes fine but service doesn't update links, here is the result from Fiddler:
Generated URI: PATCH http://{your_service_uri}/ApiUsers(1)
PATCH payload:
{ "#odata.type":"#PMWeb.Models.Models.User",
"id":1,"Name":"Ege",
"LastName":"Aydin",
"Email":"{removed}",
"Password":"{removed}",
"Genres#odata.bind":[
"http://{your_service_uri}/Genre(31)","http://{your_service_uri}/Genre(32)"
]
}
Response:
{
"#odata.context":"http://{your_service_uri}/$metadata#ApiUsers/$entity",
"id":1,
"Name":"Ege",
"LastName":"Aydin",
"Email":"{removed}",
"Password":"{removed}"
}
If I now check the content of User's genres, they are the same. Since generated payload is correct and the service accepted it, it must be something on the server that is not executed properly.

Categories

Resources